package com.yanqu.road.server.gameplayer.module.player;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.banquet.invitation.BanquetMarryInvitation;
import com.yanqu.road.entity.config.beauty.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.promotion.ItemPeerlessPromotionInfo;
import com.yanqu.road.entity.config.promotion.PromotionInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.config.skin.SkinInfo;
import com.yanqu.road.entity.decoration.MammonEffectResult;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.player.*;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.servercenter.TitleInfo;
import com.yanqu.road.entity.task.args.BeautyArgs;
import com.yanqu.road.entity.task.args.UnionRiseRankArgs;
import com.yanqu.road.entity.task.args.union.UnionActivityTaskArgs;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.bussiness.player.UserBeautyBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.beauty.BeautyPalyProto;
import com.yanqu.road.pb.beauty.BeautyProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.curio.CurioModule;
import com.yanqu.road.server.gameplayer.module.activity.greattrade.GreatTradeModule;
import com.yanqu.road.server.gameplayer.module.activity.travelbook.TravelBookModule;
import com.yanqu.road.server.gameplayer.module.banquet.BanquetModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.musicroom.MusicRoomModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.beauty.BeautyUpgradeSkillAction;
import com.yanqu.road.server.gameplayer.module.resource.GoodsResourceModule;
import com.yanqu.road.server.gameplayer.module.skin.SkinModule;
import com.yanqu.road.server.gameplayer.module.travel.TravelModule;
import com.yanqu.road.server.gameplayer.module.xiaomian.XiaoMianModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.*;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.beautyescort.BeautyEscortMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.maidian.beauty.BeautyLog;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.monopolymarket.MonopolyMarketMgr;
import com.yanqu.road.server.manger.player.WorldMessageMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.manger.systemgroup.newmonopolymarket.NewMonopolyMarketMgr;
import com.yanqu.road.server.pb.BeautyPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BeautyModule extends GeneralModule {

    public BeautyModule(GamePlayer player) {
        super(player);
    }

    private Map<Integer, UserBeauty> userBeautyMap;

    private UserBeautyData userBeautyData;

    private Map<Integer, Map<Integer, Integer>> identitySkillAdditionMap;

    private RandomHelper random = new RandomHelper();

    private Set<UserBeauty> needSyncBeauty = new HashSet<>();

    private PlayerBeautyAutoModifyCost playerBeautyAutoModifyCost = new PlayerBeautyAutoModifyCost();

    private Map<Integer, UserBeautyVoice> userBeautyVoiceMap;

    private int lastSaveTimePower = -1;          //上线前最后一次保存的用户美女体力数据 用于找回
    @Override
    public boolean afterLoadData() {
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            checkBeautyVoice(userBeauty);
        }
        return true;
    }

    @Override
    public boolean loadData() {
        userBeautyMap = UserBeautyBussiness.getUserBeautyAndSkillMap(player.getUserId());

        try {
            //指定国内渠道屏蔽同时拥有美女103001和103209的,屏蔽103209
            int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
            if (
                    channelId == 201 ||
                    channelId == 221 ||
                    channelId == 231 ||
                    channelId == 241 ||
                    channelId == 301 ||
                    channelId == 311 ||
                    channelId == 321) {
                if (userBeautyMap.containsKey(103001)){
                    if (userBeautyMap.containsKey(103209)){
                        UserBeauty beauty103209 = userBeautyMap.get(103209);
                        userBeautyMap.remove(103209);

                        //更新美女榜单,这里设置不会修改数据库里的值
                        beauty103209.setIntimacy(0);
                        beauty103209.setSkinIntimacy(0);
                        beautyChange(beauty103209);
                    }

                }
            }
        } catch (Exception e) {
            log.error(e);
        }

        userBeautyVoiceMap = UserBeautyBussiness.getUserBeautyVoiceMap(player.getUserId());
        //检测技能解锁、检测美女品质（老玩家赋予特殊品质）
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            checkQuality(userBeauty);       //赋予美女品质
            //版本更新新增用户的魅力值，变更成和亲密度一样的值
            glamourUpdate(userBeauty);
            unlockBeautySkill(userBeauty);
            BeautyMgr.isIdentitySkillUpgrade(userBeauty);        //检测美名技能
        }
        identitySkillAdditionMap = SkillMgr.initIdentitySkillAdditionMap(userBeautyMap);
        userBeautyData = UserBeautyBussiness.getUserBeautyData(player.getUserId());
        if (userBeautyData != null){
            lastSaveTimePower = userBeautyData.getEnergy();
        }
        initUserBeautyData();
        calcEnergy();
        return true;
    }

    @Override
    public boolean saveData() {
        commitBeautyChange();
        if(null != userBeautyData){
            if(userBeautyData.isInsertOption()){
                UserBeautyBussiness.addUserBeautyData(userBeautyData);
            }else if(userBeautyData.isUpdateOption()){
                UserBeautyBussiness.updateUserBeautyData(userBeautyData);
            }
        }
        if (null != userBeautyVoiceMap) {
            for (Map.Entry<Integer, UserBeautyVoice> entry : userBeautyVoiceMap.entrySet()) {
                if (entry.getValue().isInsertOption()) {
                    UserBeautyBussiness.addUserBeautyVoice(entry.getValue());
                } else if (entry.getValue().isUpdateOption()) {
                    UserBeautyBussiness.updateUserBeautyVoice(entry.getValue());
                }
            }
        }
        List<UserBeauty> beautyList = new ArrayList<>(userBeautyMap.values());
        for (UserBeauty userBeauty : beautyList) {
            if (userBeauty.isInsertOption()) {
                UserBeautyBussiness.addUserBeauty(userBeauty);
            } else if (userBeauty.isUpdateOption()) {
                UserBeautyBussiness.updateUserBeauty(userBeauty);
            }
            if(null != userBeauty.getSkillMap()){
                for(UserBeautySkill beautySkill : userBeauty.getSkillMap().values()){
                    if(beautySkill.isInsertOption()){
                        UserBeautyBussiness.addUserBeautySkill(beautySkill);
                    }else if(beautySkill.isUpdateOption()){
                        UserBeautyBussiness.updateUserBeautySkill(beautySkill);
                    }
                }
            }
        }
        return true;
    }

    public Map<Integer, UserBeauty> getUserBeautyMap() {
        return userBeautyMap;
    }

    @Override
    public void loginSendMsg() {
        SkinModule skinModule = player.getModule(SkinModule.class);
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            skinModule.recaclBeautyAttr(userBeauty, false);
        }
        syncBeautyEnergy();
        syncUserBeauty(new ArrayList<>(userBeautyMap.values()), true);
    }



    private void initUserBeautyData(){
        if(null == userBeautyData){
            UserBeautyData beautyData = new UserBeautyData();
            beautyData.setUserId(player.getUserId());
            beautyData.setEnergy(getBeautyMaxEnergy());
            beautyData.setLastRestoreTime(System.currentTimeMillis() / 1000);
            beautyData.setInsertOption();
            this.userBeautyData = beautyData;
        }
    }

    /**
     * 检测美女语音
     */
    public void checkBeautyVoice(UserBeauty userBeauty) {
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
        if (beautyInfo == null) {
            log.error("美女配置不存在,beautyId:{}", userBeauty.getBeautyId());
            return;
        }
        List<Integer> identitySoundList = beautyInfo.getIdentitySoundList();
        checkVoice(userBeauty.getBeautyId(),userBeauty.getIdentityLv(), identitySoundList);
        int genderSwapId = beautyInfo.getGenderSwapId();
        if (genderSwapId != 0){
            BeautyInfo genderSwapBeauty = BeautyMgr.getBeautyInfo(genderSwapId);
            if (genderSwapBeauty != null){
                List<Integer> swapBeautyIdentitySoundList = genderSwapBeauty.getIdentitySoundList();
                checkVoice(genderSwapBeauty.getBeautyId(),userBeauty.getIdentityLv(), swapBeautyIdentitySoundList);
            }
        }
    }

    private void checkVoice(int beautyId,int beautyIdentityLv, List<Integer> identitySoundList) {
        if (null == userBeautyVoiceMap.get(beautyId)) {
            List<Integer> voiceList = new ArrayList<>();
            voiceList.add(0);
            for (int i = 0; i < identitySoundList.size(); i++) {
                if (identitySoundList.get(i) != 0) {
                    voiceList.add(identitySoundList.get(i));
                }
                if (i >= beautyIdentityLv - 1) {
                    break;
                }
            }
            for (int skinId : player.getModule(SkinModule.class).getSkinListByBeautyId(beautyId)) {
                voiceList.add(skinId);
            }
            UserBeautyVoice userBeautyVoice = new UserBeautyVoice();
            userBeautyVoice.setUserId(player.getUserId());
            userBeautyVoice.setBeautyId(beautyId);
            userBeautyVoice.setVoiceList(new ArrayList<>(voiceList));
            userBeautyVoice.setRedDotVoiceList(new ArrayList<>(voiceList));
            userBeautyVoice.setChooseVoice(0);
            userBeautyVoice.setInsertOption();
            userBeautyVoiceMap.put(beautyId, userBeautyVoice);
        } else {
            UserBeautyVoice beautyVoice = userBeautyVoiceMap.get(beautyId);
            List<Integer> haveVoice = beautyVoice.getVoiceList();
            List<Integer> redDotVoice = beautyVoice.getRedDotVoiceList();
            for (int i = 0; i < identitySoundList.size(); i++) {
                int identitySound = identitySoundList.get(i);
                if (identitySound != 0 && !haveVoice.contains(identitySound)) {
                    haveVoice.add(identitySound);
                    redDotVoice.add(identitySound);
                }
                if (i >= beautyIdentityLv - 1) {
                    break;
                }
            }
            for (int skinId : player.getModule(SkinModule.class).getSkinListByBeautyId(beautyId)) {
                if (!haveVoice.contains(skinId)) {
                    haveVoice.add(skinId);
                    redDotVoice.add(skinId);
                }
            }
            beautyVoice.setVoiceList(haveVoice);
            beautyVoice.setRedDotVoiceList(redDotVoice);
            beautyVoice.setUpdateOption();
        }
    }

    /**
     * 清除美女语音红点
     */
    public void clearVoiceRedDot(int beautyId) {
        userBeautyVoiceMap.get(beautyId).getRedDotVoiceList().clear();
        userBeautyVoiceMap.get(beautyId).setUpdateOption();
    }

    /**
     * 美女选择语音
     */
    public int beautyChooseVoice(int beautyId, int voiceId) {
        UserBeautyVoice userBeautyVoice = userBeautyVoiceMap.get(beautyId);
        if (null == userBeautyVoice) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }
        if (!userBeautyVoice.getVoiceList().contains(voiceId)) {
            return GameErrorCode.E_BEAUTY_VOICE_NO_UNLOCK;
        }
        userBeautyVoice.setChooseVoice(voiceId);
        BeautyProto.chooseVoiceRespMsg.Builder builder = BeautyProto.chooseVoiceRespMsg.newBuilder();
        builder.setRet(0);
        builder.setVoiceMsg(BeautyPb.parseBeautyVoiceMsg(userBeautyVoice));
        player.sendPacket(ClientProtocol.U_BEAUTY_CHOOSE_VOICE, builder);
        return 0;
    }

    /**
     * 同步单条美女语音信息
     */
    public void syncBeautyVoice(UserBeautyVoice userBeautyVoice) {
        BeautyProto.SyncBeautyVoiceMsg.Builder builder = BeautyProto.SyncBeautyVoiceMsg.newBuilder();
        builder.addVoiceMsg(BeautyPb.parseBeautyVoiceMsg(userBeautyVoice));
        player.sendPacket(ClientProtocol.U_BEAUTY_SYNC_VOICE, builder);
    }

    public void syncAllBeautyVoice(Map<Integer, UserBeautyVoice> userBeautyVoiceMap) {
        BeautyProto.SyncBeautyVoiceMsg.Builder builder = BeautyProto.SyncBeautyVoiceMsg.newBuilder();
        for (Map.Entry<Integer, UserBeautyVoice> entry : userBeautyVoiceMap.entrySet()) {
            builder.addVoiceMsg(BeautyPb.parseBeautyVoiceMsg(entry.getValue()));
        }
        player.sendPacket(ClientProtocol.U_BEAUTY_SYNC_VOICE, builder);
    }

    public UserBeautyVoice getUserBeautyVoice(UserBeauty userBeauty) {
        return userBeautyVoiceMap.get(userBeauty.getBeautyId());
    }

    /**
     * 检测美女品质，老玩家特殊美女赋予特殊品质
     */
    private void checkQuality(UserBeauty userBeauty){
        if(userBeauty.getQuality() == 0){
            if(userBeauty.getBeautyId() == GameConfig.BEAUTY_ID_SILKWORM || userBeauty.getBeautyId() == GameConfig.BEAUTY_ID_CHILDE){
                userBeauty.setQuality(GameConfig.BEAUTY_QUALITY_PURPLE);
            }else {
                BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
                userBeauty.setQuality(beautyInfo.getQuality());
            }
        }
    }

    private void glamourUpdate(UserBeauty userBeauty){
        if(userBeauty.getGlamour() == 0){
            userBeauty.setGlamour(userBeauty.getIntimacy());
        }
    }

    /**
     * 同步美女精力值
     */
    private void syncBeautyEnergy() {
        BeautyProto.GetEnergyRespMsg.Builder energyData = getEnergyData();
        player.sendPacket(Protocol.U_BEAUTY_ENERGY_SYNC, energyData);
    }

    /**
     * 同步单条美女数据
     */
    public void syncUserBeauty(UserBeauty userBeauty) {
        if(null != userBeauty){
            List<UserBeauty> beautyList = new ArrayList<>();
            beautyList.add(userBeauty);
            syncUserBeauty(beautyList, false);
        }
    }

    /**
     * 同步美女数据
     */
    public void syncUserBeauty(List<UserBeauty> beautyList, boolean login) {
        BeautyProto.BeautyListMsg.Builder listMsg = BeautyPb.parseBeautyListMsg(beautyList);
        if (login) {
            player.sendPacket(Protocol.U_BEAUTY_LOGIN_DATA, listMsg);
        } else {
            synchronized (needSyncBeauty) {
                needSyncBeauty.addAll(beautyList);
            }
        }
    }

    public void commitBeautyChange() {
        List<UserBeauty> list;
        synchronized (needSyncBeauty) {
            list = new ArrayList<>(needSyncBeauty);
            needSyncBeauty.clear();
        }
        if (list.isEmpty()) {
            return;
        }
        BeautyProto.BeautyListMsg.Builder listMsg = BeautyPb.parseBeautyListMsg(list);
        player.sendPacket(Protocol.U_BEAUTY_DATA_SYNC, listMsg);
    }

    /**
     * 解锁美女
     */
    public int addBeauty(int beautyId, eLogMoneyType master, eLogMoneyType son) {
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
        if (null == beautyInfo) {
            AutoLogMgr.add(new LogGetBeauty(player.getUserId(), beautyId, master.getValue(), son.getValue()));
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }
        UserBeauty userBeauty = getUserBeauty(beautyId);
        if (BeautyMgr.isUserBeautyExist(userBeauty)) {
            AutoLogMgr.add(new LogGetBeauty(player.getUserId(), beautyId, master.getValue(), son.getValue()));
            return GameErrorCode.E_BEAUTY_ALREADY_EXIST;
        }
        userBeauty = initUserBeauty(beautyInfo);
        userBeautyMap.put(userBeauty.getBeautyId(), userBeauty);
        int intimacy = beautyInfo.getInitIntimacy();
        addIntimacy(userBeauty, intimacy, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyUnlock.getValue());
        int initGlamour = beautyInfo.getInitGlamour();
        addGlamour(userBeauty,initGlamour, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyUnlock.getValue());

        //主角皮肤对美女影响
        player.getModule(SkinModule.class).recaclBeautyAttr(userBeauty, true);

        //初始化美名效果
        calcIdentitySkillAddition(userBeauty);
        //自动提升美名
        autoPromotion(userBeauty);
        onBeautyChange(userBeauty);

        //生成婚帖
        BanquetMarryInvitation inv = new BanquetMarryInvitation();
        inv.setBeautyId(beautyId);
        inv.setIntimacy(userBeauty.getTotalIntimacy());
        player.getModule(BanquetModule.class).makeInvitation(eBanquetInvitationType.MarryInvitation.getValue(), JSON.toJSONString(inv));
        addBeautyFlag(beautyId);

        //成就、任务
        player.notifyListener(eGamePlayerEventType.BeautyTotalCount.getValue(), new BeautyArgs(userBeautyMap));
        player.notifyListener(eGamePlayerEventType.BeautyFundNum.getValue(), new BeautyArgs(userBeautyMap));
        player.notifyListener(eGamePlayerEventType.BeautyTotalLevel.getValue(), new BeautyArgs(userBeautyMap));
        syncUserBeauty(userBeauty);
        checkBeautyVoice(userBeauty);
        syncBeautyVoice(getUserBeautyVoice(userBeauty));

        AutoLogMgr.add(new LogGetBeauty(player.getUserId(), beautyId, master.getValue(), son.getValue()));

        DataAnalyticsMgr.trackBeautyGet(player, beautyInfo, userBeauty);

        player.getModule(CurioModule.class).checkAllCurioItemSpecialSkill();

        if (SystemOpenMgr.systemOpen(player, eSystemId.TravelBook.getValue())) {
            player.getModule(TravelBookModule.class).initBeautyAlbumData(beautyId); // 旅行册初始化
        }

        return 0;
    }

    /**
     * 初始化美女
     */
    private UserBeauty initUserBeauty(BeautyInfo beautyInfo) {
        UserBeauty userBeauty;
        userBeauty = new UserBeauty();
        userBeauty.setBeautyId(beautyInfo.getBeautyId());
        userBeauty.setUserId(player.getUserId());
        userBeauty.setIntimacy(0);
        userBeauty.setGlamour(0);
        userBeauty.setLevel(1);
        userBeauty.setSkill1(1);
        userBeauty.setSkill2(1);
        userBeauty.setSkillExp(0);
        userBeauty.setIdentityLv(1);
        userBeauty.setIdentitySkillLv(1);
        userBeauty.setChildCount(0);
        userBeauty.setCreateTime(System.currentTimeMillis() / 1000);
        userBeauty.setTravelTimes(0);
        userBeauty.setBathTimes(0);
        userBeauty.setSkinId(0);
        userBeauty.setSkinIntimacy(0);
        userBeauty.setSkinGlamour(0);
        userBeauty.setEscortSkill1(1);
        userBeauty.setEscortSkill2(1);
        userBeauty.setEscortExp(0);
        userBeauty.setQuality(beautyInfo.getQuality());
        userBeauty.setSkinSkill1(0);
        userBeauty.setSkinSkill2(0);
        userBeauty.setPromotionSkill(0);
        userBeauty.setInsertOption();
        return userBeauty;
    }

    /**
     * 根据亲密度解锁美女技能
     */
    private List<Integer> unlockBeautySkill(UserBeauty userBeauty) {
        List<Integer> unlockSkillList = new ArrayList<>();
        Map<Integer, BeautySkillInfo> beautySkillInfoMap = BeautyMgr.getBeautySkillInfoMap();
        if(null != beautySkillInfoMap){
            int length = beautySkillInfoMap.size();
            for(int i = 1; i <= length; i++){
                BeautySkillInfo beautySkillInfo = beautySkillInfoMap.get(i);
                if(userBeauty.getTotalIntimacy() >= beautySkillInfo.getNeedIntimacy()){//达到亲密度
                    if(!userBeauty.hasBeautySkill(beautySkillInfo.getSkillPos())){
                        unlockSkillList.add(beautySkillInfo.getSkillPos());
                        UserBeautySkill userBeautySkill = initUserBeautySkill(player.getUserId(), userBeauty.getBeautyId(), beautySkillInfo.getSkillPos(),
                                1, 0);
                        userBeauty.addBeautySkill(userBeautySkill.getSkillPos(), userBeautySkill);
                    }
                }
            }
        }
        return unlockSkillList;
    }

    /**
     * 美女升级门客技能
     *
     * @param beautyId
     * @param type
     * @param batch 1或者10连
     * @return
     */
    public int beautyUpgradeSkill(int beautyId, int type, int position, int batch) {
        BeautyUpgradeSkillAction action = BeautyUpgradeSkillAction.getAction(beautyId, position, type, batch, this, player);
        if(action == null){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        action.upgrade();
        if(action.getRet() != 0){
            return action.getRet();
        }

        UserBeauty userBeauty = getUserBeauty(beautyId);
        if (eBeautySkillType.GlamourAddPatronsFixedValue.getValue() == type
                || eBeautySkillType.GlamourAddPatronsMultiValue.getValue() == type
                || eBeautySkillType.EscortAddPatronsFixedValue.getValue() == type
                || eBeautySkillType.EscortAddPatronsMultiValue.getValue() == type
                || eBeautySkillType.PeerlessSkill.getValue() == type
                || eBeautySkillType.PeerlessPromotionSkill.getValue() == type
                || eBeautySkillType.MusicRoomAddPatrons.getValue() == type
                || eBeautySkillType.TravelBookAlbumSkill.getValue() == type) {
            //成就、任务
            userBeautyData.setTotalFateSkillUpgradeTimes(userBeautyData.getTotalFateSkillUpgradeTimes() + action.getRealBatch());
            player.notifyListener(eGamePlayerEventType.BeautyTotalFateSkillUpgradeTimes.getValue(), userBeautyData);
            if (type == 3 || type == 4) {
                player.notifyListener(eGamePlayerEventType.BeautyEscortSkillUpgradeTimes.getValue(), action.getRealBatch());
                player.notifyListener(eGamePlayerEventType.UnionBeautyEscortSkillUpgradeTimes.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, action.getRealBatch(), player.getUserInfo().getUnionUid()));
            }
            // 晋升无双技能会提升亲密、魅力
            if (type == 8) {
                player.getModule(SkinModule.class).recaclBeautyAttr(userBeauty, true);
            }

            //缘分美女关联门客属性变更
            onBeautyChange(userBeauty);
        } else {
            player.getModule(PatronsModule.class).onPatronsChange(null);
        }
        // 同步美女数据
        syncUserBeauty(userBeauty);

//        player.notifyListener(eGamePlayerEventType.BeautyTotalUpgradeTimes.getValue(), new BeautyArgs(userBeautyMap));
//        player.notifyListener(eGamePlayerEventType.BeautyTotalLevel.getValue(), new BeautyArgs(userBeautyMap));
        int oldLv = action.getOldLv();
        int nowLv = oldLv + action.getRealBatch();
        SkillInfo skillInfo = action.getSkillInfo();

        LogMgr.addLogBeautyUpgrade(player.getUserId(), beautyId, type, oldLv, nowLv, PropertyHelper.parsePropertyToString(action.getConsumer()));

        if (type == eBeautySkillType.MusicRoomAddPatrons.getValue()) {
            BeautyLog.trackBeautyMusicRoomSkillUp(player, beautyId, skillInfo.getId(), nowLv);
        }

        if (skillInfo.getType() == eSkillType.BanquetJoinPopularitySkill.getValue()) {
            player.getModule(BanquetModule.class).syncAutoInfo();
        }
        return 0;
    }

    /**
     * 改装美女技能
     * @param beautyId 美女标识
     * @param skillPos 技能位置
     * @param isCustomize 是否定制
     * @return 改装结果
     */
    public BeautyModifySkillResult beautyModifySkill(int beautyId, int skillPos, boolean isCustomize, boolean isAuto) {
        BeautyModifySkillResult result = new BeautyModifySkillResult();
        UserBeauty userBeauty = getUserBeauty(beautyId);
        if(!BeautyMgr.isUserBeautyExist(userBeauty)){
            result.setRet(GameErrorCode.E_BEAUTY_NO_FOUND);
            return result;
        }
        UserBeautySkill userBeautySkill = userBeauty.getSkillMap().get(skillPos);
        if(null == userBeautySkill){
            result.setRet(GameErrorCode.E_BEAUTY_SKILL_NO_FOUND);
            return result;
        }
        Property consume;
        if(isCustomize){//定制改装
            consume = new Property(GameConfig.BEAUTY_SKILL_CUSTOM_MODIFY_ITEM, BigInteger.ONE);
            if (!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Beauty, eLogMoneyType.BeautyCustomModifySkill)) {
                result.setRet(GameErrorCode.E_BAG_ITEM_NO_ENOUGH);
                return result;
            }
            if (isAuto) {
                playerBeautyAutoModifyCost.addItemCost(consume.getCountByGoodsId(GameConfig.BEAUTY_SKILL_CUSTOM_MODIFY_ITEM).longValue());
            }
        }else {//消耗银两改装
            BigInteger silver = BeautyMgr.getModifySkillCost(userBeautySkill.getSkillModifyTimes());
            consume = new Property(GameConfig.GAME_MONEY_SILVER, silver);
            if (!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Beauty, eLogMoneyType.BeautyModifySkill)) {
                result.setRet(GameErrorCode.E_BAG_SILVER_NO_ENOUGH);
                return result;
            }
            if (isAuto) {
                playerBeautyAutoModifyCost.addSliverCost(consume.getCountByGoodsId(GameConfig.GAME_MONEY_SILVER).longValue());
            }
        }
        //获取随机技能值
        int skillValue = BeautyMgr.getRandomSkillValue(isCustomize);
        int oldSkillValue = userBeautySkill.getSkillValue();
        boolean isReplace = false;
        if(skillValue > oldSkillValue){//新值大于旧值，进行替换
            userBeautySkill.setSkillValue(skillValue);
            isReplace = true;
            onBeautyChange(userBeauty);
        }
        //技能改装次数增加
        if(!isCustomize) {//只记录非定制改装次数
            userBeautySkill.setSkillModifyTimes(userBeautySkill.getSkillModifyTimes() + 1);
        }
        UserBeautySkill tempSkill = initUserBeautySkill(player.getUserId(), userBeauty.getBeautyId(), skillPos, skillValue, userBeautySkill.getSkillModifyTimes());
        result.setRet(0);
        result.setBeautySkill(tempSkill);
        result.setRepalce(isReplace);
        long totalModifyTimes = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.BeautyTotalSkillModifyTimes);
        totalModifyTimes++;
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.BeautyTotalSkillModifyTimes, totalModifyTimes);
        //任务、成就
        player.notifyListener(eGamePlayerEventType.BeautySkillModifyTimes.getValue(), beautyId);
        player.notifyListener(eGamePlayerEventType.BeautyModifyBuildingTimes.getValue(), beautyId);
        player.notifyListener(eGamePlayerEventType.BeautyTotalSkillModifyTimes.getValue(), totalModifyTimes);
        if(!isAuto) {
            AutoLogMgr.add(new LogBeautySkillRefine(player.getUserId(), beautyId, skillPos, skillValue, isCustomize, PropertyHelper.parsePropertyToString(consume)));
        }
        if(isReplace){
            AutoLogMgr.add(new LogBeautySkillModify(player.getUserId(), beautyId, skillPos, oldSkillValue, skillValue));
        }
        result.setCurValue(userBeautySkill.getSkillValue());

        //v4.1 改为替换
        //if(isReplace) {
        //    DataAnalyticsMgr.trackBeautySkillUp(player, userBeauty, skillPos, 0, userBeautySkill.getSkillValue());
        //}
        return result;
    }

    /**
     * 美女传唤
     * @param type 1.随机 2.一键传唤精力上线 3.一键传唤一百次
     * @param assistantFlag 是否是小玉一键处理。true：是，false：不是
     * @return
     */
    public BeautyTrystResult beautyTryst(int type, boolean assistantFlag) {
        BeautyTrystResult result = new BeautyTrystResult();
        int energy;
        int unlockBeautyCount = getUnlockBeautyCount();
        if(unlockBeautyCount <= 0){//没有美女可以传唤
            result.setRet(GameErrorCode.E_BEAUTY_NO_FOUND);
            return result;
        }
        switch (type) {
            case 1://随机传唤
                energy = getBeautyEnergy();
                if (energy < 1) {
                    //6.4.0优化，小玉一键不触发现金礼包
                    if (!assistantFlag) {
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
                    }
                    result.setRet(GameErrorCode.E_BEAUTY_ENERGY_NOT_ENOUGH);
                    break;
                }
                BeautyTrystGain gain = randomTryst(true);
                result.addResult(gain);
                break;
            case 2:// 一键随机传唤
                if (!canTrystAll()) {
                    result.setRet(GameErrorCode.E_BEAUTY_ALL_TRYST_TITLE_NO_ENOUGH);
                    break;
                }
                energy = getBeautyEnergy();
                if (energy < 1) {
                    //6.4.0优化，小玉一键不触发现金礼包
                    if (!assistantFlag) {
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
                    }
                    result.setRet(GameErrorCode.E_BEAUTY_ENERGY_NOT_ENOUGH);
                    break;
                }
                result = trystAll();
                break;
            case 3://一键传唤一百次,小于100次精力有多少用多少
                if (!canTrystHundredTimes()) {
                    result.setRet(GameErrorCode.E_BEAUTY_QUICK_TRYST_TITLE_NO_ENOUGH);      //等级不够
                    break;
                }
                energy = Math.min(getBeautyEnergy(), 100);
                if (energy < 1) {
                    //6.4.0优化，小玉一键不触发现金礼包
                    if (!assistantFlag) {
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                        player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
                    }
                    result.setRet(GameErrorCode.E_BEAUTY_ENERGY_NOT_ENOUGH);
                    break;
                }
                result = quickTrystHundredTime(energy);
                break;
            default:
                result.setRet(GameErrorCode.E_BEAUTY_WRONG_TRYST_TYPE);
                break;
        }
        energy = getBeautyEnergy();
        if(energy < 1){
            //6.4.0优化，小玉一键不触发现金礼包
            if (!assistantFlag) {
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            }
        }
        return result;
    }

    /**
     * 美女宠幸
     * @param type 1.出游 2.沐浴
     */
    public BeautyFavorResult beautyFavor(List<Integer> beautyIdList,int type) {
        BeautyFavorResult result = new BeautyFavorResult();
        if(!checkFavorCurrency(beautyIdList,type)){
            result.setRet(GameErrorCode.E_BEAUTY_FAVOR_COST);
            if(2 == type){//沐浴道具不足，触发现金礼包
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            }
            return result;
        }
        return favorAll(beautyIdList,type);
    }

    //检查美女宠幸的消耗是否足够
    private boolean checkFavorCurrency(List<Integer> beautyIdList,int type){
        Property cost = getFavorCost(beautyIdList,type);
        return player.getModule(CurrencyModule.class).currencyIsEnough(cost);
    }

    private Property getFavorCost(List<Integer> beautyIdList,int type){
        Property cost = new Property();
        if(type == 1){//出游
            int needMoney = 0;
            for(int beautyId : beautyIdList){
                UserBeauty userBeauty = getUserBeauty(beautyId);
                needMoney += BeautyMgr.getTravelCost(userBeauty.getTravelTimes());
            }
            cost.addProperty(GameConfig.GAME_MONEY_INGOTS,BigInteger.valueOf(needMoney));
        }else if(type == 2){//沐浴
            cost.addProperty(PropertyHelper.parseStringToProperty(GameConfig.BEAUTY_FAVOR_BATH_COST));
            cost.rideProperty(beautyIdList.size());
        }
        return cost;
    }

    /**
     * 多人运动
     */
    private BeautyFavorResult favorAll(List<Integer> beautyIdList,int type) {
        BeautyFavorResult favorResult = new BeautyFavorResult();
        Property cost = getFavorCost(beautyIdList,type);
        if(!player.getModule(CurrencyModule.class).removeCurrency(cost,eLogMoneyType.Beauty,eLogMoneyType.BeautyFavor)){
            favorResult.setRet(GameErrorCode.E_BEAUTY_FAVOR_COST);
            if(2 == type){//沐浴道具不足，触发现金礼包
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            }
            return favorResult;
        }
        for(Integer beautyId : beautyIdList){
            UserBeauty userBeauty = getUserBeauty(beautyId);
            BeautyFavorGain gain = favor(userBeauty,type);
            favorResult.addResult(gain);
            if(type == 1){//出游
                userBeauty.setTravelTimes(userBeauty.getTravelTimes()+1);
                player.notifyListener(eGamePlayerEventType.BeautyTotalTravelTimes.getValue(), new BeautyArgs(userBeautyMap));
                player.notifyListener(eGamePlayerEventType.BeautyTotalFavorTimes.getValue(), new BeautyArgs(userBeautyMap));

                AutoLogMgr.add(new LogBeautyFavor(player.getUserId(), userBeauty.getBeautyId(),type, userBeauty.getTravelTimes(),
                        PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_INGOTS,BigInteger.valueOf(BeautyMgr.getTravelCost(userBeauty.getTravelTimes())))),
                        PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_BEAUTY_EXP,BigInteger.valueOf(gain.getAddExp())))
                ));

                DataAnalyticsMgr.trackBeautyTrip(player, userBeauty, type);
            }else if(type == 2){//沐浴
                userBeauty.setBathTimes(userBeauty.getBathTimes()+1);
                player.notifyListener(eGamePlayerEventType.BeautyTotalBathTimes.getValue(), new BeautyArgs(userBeautyMap));
                player.notifyListener(eGamePlayerEventType.BeautyTotalFavorTimes.getValue(), new BeautyArgs(userBeautyMap));

                AutoLogMgr.add(new LogBeautyFavor(player.getUserId(), userBeauty.getBeautyId(),type, userBeauty.getBathTimes(),
                        GameConfig.BEAUTY_FAVOR_BATH_COST,
                        PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_BEAUTY_EXP,BigInteger.valueOf(gain.getAddExp())))));

                DataAnalyticsMgr.trackBeautyTrip(player, userBeauty, type);
            }
            syncUserBeauty(userBeauty);
        }
        return favorResult;
    }

    /**
     * 美女赏赐
     * 增加美女亲密度
     */
    public int giveGift(UserBeauty userBeauty, int addValue, int giftId, int giftCount) {
        //消耗
        Property beautyGift = new Property(giftId, BigInteger.valueOf(giftCount));
        if (!player.getModule(CurrencyModule.class).removeCurrency(beautyGift, eLogMoneyType.Beauty, eLogMoneyType.BeautyGift)) {
            player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
            player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(giftId);
        if (GoodsMgr.isBeautyIntimacy(goodsInfo)) {
            //增加美女亲密度
            addIntimacy(userBeauty, addValue, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyGift.getValue());
        }else if(GoodsMgr.isBeautyGlamour(goodsInfo)){
            //增加美女魅力值
            addGlamour(userBeauty, addValue, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyGift.getValue());
        }

        //增加美女累计赏赐次数
        userBeauty.setTotalRewardTimes(userBeauty.getTotalRewardTimes() + giftCount);
        //同步美女
        syncUserBeauty(userBeauty);
        onBeautyChange(userBeauty);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.BeautyRewardTimes.getValue(), giftCount);
        player.notifyListener(eGamePlayerEventType.BeautyTotalRewardTimes.getValue(), new BeautyArgs(userBeautyMap));

        //埋点
        if (GoodsMgr.isBeautyIntimacy(goodsInfo)) {
            //亲密度
            //DataAnalyticsMgr.trackSendBeautyGift(player, userBeauty, giftId, addValue, 1);
        }else if(GoodsMgr.isBeautyGlamour(goodsInfo)){
            //DataAnalyticsMgr.trackSendBeautyGift(player, userBeauty, giftId, addValue, 2);
        }
        return 0;
    }

    /**
     * 晋升
     */
    public int beautyPromotion(int beautyId) {
        UserBeauty userBeauty = userBeautyMap.get(beautyId);
        if(!BeautyMgr.isUserBeautyExist(userBeauty)){
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        BeautyIdentityInfo nextIdentityInfo = BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv() + 1);
        if (null == nextIdentityInfo) {
            return GameErrorCode.E_BEAUTY_IDENTITY_LEVEL_MAX;
        }

        BeautyIdentityInfo identityInfo = BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv());
        if (userBeauty.getTotalIntimacy() < identityInfo.getNeedIntimacy()) {//亲密度不够
            return GameErrorCode.E_BEAUTY_INTIMACY_NO_ENOUGH;
        }

        if (userBeauty.getTotalGlamour() < identityInfo.getNeedGlamour()) {//魅力值不够
            return GameErrorCode.E_BEAUTY_GLAMOUR_NO_ENOUGH;
        }
        if (BeautyMgr.getTotalBeautyCount(userBeautyMap) < identityInfo.getNeedBeautyCount()){//美女数量不足
            return GameErrorCode.E_BEAUTY_COUNT_NO_ENOUGH;
        }

        //增加美名等级
        addBeautyIdentityLv(userBeauty);
        onBeautyChange(userBeauty);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.BeautyTotalPromotionTimes.getValue(), new BeautyArgs(userBeautyMap));
        if(null == BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv() + 1)){//晋升到最大等级
            WorldMessageMgr.worldNotify(eMessageType.BeautyPromotionMaxLv.getValue(), player.getUserInfo().getCity(), player.getTitleId(),
                    player.getUserInfo().getNickName(), beautyId, userBeauty.getIdentityLv());
        }

        DataAnalyticsMgr.trackBeautyPromotion(player, userBeauty);
        checkBeautyVoice(userBeauty);
        syncBeautyVoice(getUserBeautyVoice(userBeauty));
        return 0;
    }

    /**
     * 获取某职业的门客，传入参数为0，则纯随机
     */
    public UserBeauty getRandomBeauty(int occupation){
        List<UserBeauty> dataList = new ArrayList<>();
        for(UserBeauty userBeauty : userBeautyMap.values()){
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
            if(beautyInfo.getOccupation() == occupation || 0 == occupation){
                // 织布中的美女排除
                if (!player.getModule(ColdRoomModule.class).isBeautyFree(userBeauty.getBeautyId())){
                    continue;
                }
                dataList.add(userBeauty);
            }
        }
        if(dataList.size() > 0){
            int randomValue = random.next(0, dataList.size());
            return dataList.get(randomValue);
        }
        return null;
    }

    public int getIdentitySkillAddition(int skillType, int param){
        return SkillMgr.getSkillAdditionFromMap(skillType, param, identitySkillAdditionMap);
    }

    private boolean canTrystAll() {
        return player.getTitleId() >= GameConfig.ALL_TRYST_BEAUTY_NEED_TITLE;
    }

    private boolean canTrystHundredTimes(){
        return player.getTitleId() >= GameConfig.BEAUTY_TRYST_QUICK_LIMIT || VipMgr.getVipLv(player.getUserInfo().getVipExp())>=GameConfig.BEAUTY_TRYST_QUICK_LIMIT_VIP;
    }

    /**
     * 自动提升美名
     */
    private void autoPromotion(UserBeauty userBeauty){
        if(!BeautyMgr.isUserBeautyExist(userBeauty)){
            return;
        }
        boolean isChange = false;
        do {
            BeautyIdentityInfo nextIdentityInfo = BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv() + 1);
            if (null == nextIdentityInfo) {
                break;
            }

            BeautyIdentityInfo identityInfo = BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv());
            if (userBeauty.getTotalIntimacy() < identityInfo.getNeedIntimacy()) {//亲密度不够
                break;
            }
            if (userBeauty.getTotalGlamour() < identityInfo.getNeedGlamour()) {//魅力不够
                break;
            }

            //增加美名等级
            addBeautyIdentityLv(userBeauty);
            isChange = true;
        }while (userBeauty.getIdentityLv() < BeautyMgr.getMaxBeautyIdentityLv());
        if(isChange) {
            //成就、任务
            player.notifyListener(eGamePlayerEventType.BeautyTotalPromotionTimes.getValue(), new BeautyArgs(userBeautyMap));
        }
    }

    /**
     * 增加美名
     */
    private void addBeautyIdentityLv(UserBeauty userBeauty){
        userBeauty.setIdentityLv(userBeauty.getIdentityLv() + 1);
        if(BeautyMgr.isIdentitySkillUpgrade(userBeauty)){
            calcIdentitySkillAddition(userBeauty);
            //如果是增加门客能力的美名技能，通知刷新一下门客能力
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
            SkillInfo skillInfo = SkillMgr.getSkillInfo(beautyInfo.getIdentitySkillId());
            if(null != skillInfo){
                int param3 = skillInfo.getParamList().get(3).intValue();
                if(param3 > 0){
                    PatronsModule patronsModule = player.getModule(PatronsModule.class);
                    UserPatrons userPatrons = patronsModule.getUserPatrons(param3);
                    if(null != userPatrons) {
                        patronsModule.onPatronsChange(userPatrons);
                    }
                }
            }
        }
        //大商途 技能效果
        player.getModule(GreatTradeModule.class).calBeautySkill(userBeauty);

        checkBeautyMusicRoomSkill(userBeauty);
    }

    private void calcIdentitySkillAddition(UserBeauty userBeauty){
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
        SkillInfo skillInfo = SkillMgr.getSkillInfo(beautyInfo.getIdentitySkillId());
        if(null == skillInfo){
            return;
        }
        Map<Integer, Integer> additionMap = new ConcurrentHashMap<>();
        for(UserBeauty tempBeauty : userBeautyMap.values()){
            BeautyInfo tempBeautyInfo = BeautyMgr.getBeautyInfo(tempBeauty.getBeautyId());
            SkillInfo tempSkillInfo = SkillMgr.getSkillInfo(tempBeautyInfo.getIdentitySkillId());
            if(null == tempSkillInfo){
                continue;
            }
            if(tempSkillInfo.getType() == skillInfo.getType()){
                int param3 = tempSkillInfo.getParamList().get(2);
                int addition = 0;
                if(additionMap.containsKey(param3)){
                    addition = additionMap.get(param3);
                }
                addition += SkillMgr.getSkillAddition(tempSkillInfo, tempBeauty.getIdentitySkillLv());
                additionMap.put(param3, addition);
            }
        }
        identitySkillAdditionMap.put(skillInfo.getType(), additionMap);
    }

    /**
     * 添加亲密度
     */
    public void addIntimacy(UserBeauty userBeauty, int intimacy, int master, int son) {
        if(null == userBeauty){
            return;
        }
        if(intimacy <= 0){
            return;
        }
        int oldIntimacy = userBeauty.getTotalIntimacy();
        userBeauty.setIntimacy(userBeauty.getIntimacy() + intimacy);
        intimacyChange(userBeauty, oldIntimacy, intimacy, master, son, true);
        beautyChange(userBeauty);
    }

    /**
     * 亲密度变更
     */
    public void intimacyChange(UserBeauty userBeauty, int oldIntimacy, int intimacy, int master, int son, boolean isAddLog) {
        if(isAddLog) {
            AutoLogMgr.add(new LogBeautyIntimacy(player.getUserId(), userBeauty.getBeautyId(), oldIntimacy, userBeauty.getTotalIntimacy(), intimacy, master, son));
        }
        //解锁美女技能
        unlockBeautySkill(userBeauty);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.BeautyTotalIntimacy.getValue(), new BeautyArgs(userBeautyMap));
        player.notifyListener(eGamePlayerEventType.BeautyMaxIntimacy.getValue(), new BeautyArgs(userBeautyMap));
        //亲密度提升冲榜
        int riseIntimacy = intimacy;
        if(eLogMoneyType.BeautyUnlock.getValue() == son){//美女初始亲密度不算入冲榜
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
            riseIntimacy = riseIntimacy - beautyInfo.getInitIntimacy();
            if(riseIntimacy < 0){
                riseIntimacy = 0;
            }
        }
        //不算初始亲密度
        if (riseIntimacy != 0) {
            player.notifyListener(eGamePlayerEventType.BeautyAddIntimacy.getValue(), riseIntimacy);
            player.notifyListener(eGamePlayerEventType.IntimacyRiseRank.getValue(), riseIntimacy);
            player.notifyListener(eGamePlayerEventType.UnionIntimacyRiseRank.getValue(), new UnionRiseRankArgs(UnionRiseRankArgs.NOTIFY_TYPE_NORMAL,
                    BigInteger.valueOf(riseIntimacy), player.getUserInfo().getUnionUid()));
        }
        //亲密度榜
        BigInteger totalIntimacy = BigInteger.valueOf(BeautyMgr.getTotalIntimacy(userBeautyMap));
        RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), totalIntimacy, eRankType.BeautyIntimacy.getValue(), "");
        skinRankChange(userBeauty);
        // 修改userInfo
        player.getUserInfo().setTotalIntimacy(totalIntimacy);
    }

    /**
     * 增加魅力值
     */
    public void addGlamour(UserBeauty userBeauty, int glamour, int master, int son) {
        if(null == userBeauty){
            return;
        }
        if(glamour <= 0){
            return;
        }
        int oldGlamour = userBeauty.getTotalGlamour();
        userBeauty.setGlamour(userBeauty.getGlamour() + glamour);
        glamourChange(userBeauty, oldGlamour, glamour, master, son, true);
    }

    /**
     * 魅力变更
     */
    public void glamourChange(UserBeauty userBeauty, int oldGlamour, int glamour, int master, int son, boolean isAddLog) {
        if(isAddLog) {
            AutoLogMgr.add(new LogBeautyGlamour(player.getUserId(), userBeauty.getBeautyId(), oldGlamour, userBeauty.getTotalGlamour(), glamour, master, son));
        }
        //成就、任务
        player.notifyListener(eGamePlayerEventType.BeautyTotalGlamour.getValue(), new BeautyArgs(userBeautyMap));
        player.notifyListener(eGamePlayerEventType.BeautyMaxGlamour.getValue(), new BeautyArgs(userBeautyMap));
        //魅力值提升冲榜
        int riseGlamour = glamour;
        if(eLogMoneyType.BeautyUnlock.getValue() == son){//美女初始魅力不算入冲榜
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
            riseGlamour = riseGlamour - beautyInfo.getInitGlamour();
            if(riseGlamour < 0){
                riseGlamour = 0;
            }
        }
        //不算初始魅力值
        if (riseGlamour != 0) {
            player.notifyListener(eGamePlayerEventType.BeautyAddGlamour.getValue(), riseGlamour);
            player.notifyListener(eGamePlayerEventType.UnionBeautyAddGlamour.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, riseGlamour, player.getUserInfo().getUnionUid()));
            player.notifyListener(eGamePlayerEventType.GlamourRiseRank.getValue(), riseGlamour);
            player.notifyListener(eGamePlayerEventType.UnionGlamourRiseRank.getValue(), new UnionRiseRankArgs(UnionRiseRankArgs.NOTIFY_TYPE_NORMAL,
                    BigInteger.valueOf(riseGlamour), player.getUserInfo().getUnionUid()));
        }
        //新门客基金-美女才华
        player.notifyListener(eGamePlayerEventType.PatronsFundBeautyGlamour.getValue(), userBeauty);
        //新门客基金最新版-美女才华
        player.notifyListener(eGamePlayerEventType.NewPatronsFundBeautyCh.getValue(), 0);
        skinRankChange(userBeauty);

        //走镖魅力变更
        BeautyEscortMgr.addNeedUploadUserInfo(player, userBeauty.getBeautyId());
        // 榷场魅力变更
        MonopolyMarketMgr.addNeedUploadObjectInfo(player,eMonopolyMarketResType.RES_QUEEN.getValue(),userBeauty.getBeautyId());
        NewMonopolyMarketMgr.addNeedUploadObjectInfo(player,eMonopolyMarketResType.RES_QUEEN_NEW.getValue(), userBeauty.getBeautyId());
    }

    public void skinRankChange(UserBeauty userBeauty) {
        try {
            long serverId = ConfigHelper.getLong("serverId");
            ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
            int channelId = 0;
            if(serverInfo != null){
                channelId = serverInfo.getChannelId();
            }
            SkinModule skinModule = player.getModule(SkinModule.class);
            for (int skinId : SkinMgr.getSkinListByRoleId(eSkinType.Beauty, userBeauty.getBeautyId())) {
                UserSkin userSkin  = skinModule.getUserSkinMap().get(skinId);
                if (userSkin != null) {
                    int rankSkinId = skinId;
                    SkinInfo skinInfo = SkinMgr.getSkinInfo(skinId);
                    if(skinInfo == null){
                        continue;
                    }
                    //大陆美女2合1
                    rankSkinId = SkinMgr.rankBeautySkinIdTransform(rankSkinId);
//                    if(eChannelType.isMainLandChannel(channelId)){
//                        if(ConfigMgr.isBeautySetOne(userBeauty.getBeautyId())){
//                            rankSkinId = Integer.parseInt(skinInfo.getIcon());
//                        }
//                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("value", userBeauty.getTotalIntimacy() + "");
                    jsonObject.put("glamour", userBeauty.getTotalGlamour() + "");
                    RankMgr.changeUserRank(eBigRankType.Skin.getValue(), player.getUserId(), BigInteger.valueOf(userSkin.getLevel()), rankSkinId, jsonObject.toJSONString());
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 百连传唤！
     */
    private BeautyTrystResult quickTrystHundredTime(int times) {
        BeautyTrystResult trystResult = new BeautyTrystResult();
        for (int i = 0; i < times; i++) {
            BeautyTrystGain gain = randomTryst(true);
            trystResult.addResult(gain);
        }
        return trystResult;
    }

    /**
     * 一键消耗所有精力上限传唤
     */
    private BeautyTrystResult trystAll() {
        BeautyTrystResult trystResult = new BeautyTrystResult();
        int energy = getBeautyEnergy();
        int maxEnergy = getBeautyMaxEnergy();
        if(energy > maxEnergy){
            energy = maxEnergy;
        }
        for (int i = 0; i < energy; i++) {
            BeautyTrystGain gain = randomTryst(true);
            trystResult.addResult(gain);
        }
        return trystResult;
    }

    /**
     * 随机传唤 消耗精力
     */
    private BeautyTrystGain randomTryst(boolean notifyTask) {
        if (getBeautyEnergy() > 0) {
            int appointBeautyId = player.getModule(TravelModule.class).removeBeautyTrystEvent();
            UserBeauty beauty;
            //游历指定传唤事件，并且没有在冷宫
            if(appointBeautyId > 0){
                if(player.getModule(ColdRoomModule.class).isBeautyFree(appointBeautyId)) {
                    beauty = getUserBeauty(appointBeautyId);
                    if(null == beauty) {
                        log.warn("randomTryst appoint beautyId:{},but beauty no find", appointBeautyId);
                        beauty = getRandomBeauty();
                    }
                }else {
                    log.warn("randomTryst appoint beautyId:{},but beauty is in coolRoom", appointBeautyId);
                    beauty = getRandomBeauty();
                }
            }else {
                beauty = getRandomBeauty();
            }
            if (null != beauty) {
                BeautyTrystGain result = tryst(beauty,notifyTask);
                if(null != result){
                    AutoLogMgr.add(new LogBeautyTryst(player.getUserId(), beauty.getBeautyId(), appointBeautyId, result.getChildUid(), result.isMultiChild(), result.isTravelEventMultiChild()));
                }
                return result;
            }
        }
        return new BeautyTrystGain();
    }

    /**
     * 获取随机美女
     */
    public UserBeauty getRandomBeauty() {
        List<UserBeauty> randomList = getRandomBeautyList();
        if(randomList.size() > 0) {
            int size = randomList.size();
            int randomNum = random.next(0, size);
            return randomList.get(randomNum);
        }
        return null;
    }

    /**
     * 获取可随机美女集合 (排除织布中的美女)
     */
    public List<UserBeauty> getRandomBeautyList() {
        List<UserBeauty> randomList = new ArrayList<>();
        for(UserBeauty beauty : userBeautyMap.values()){
            if(BeautyMgr.isUserBeautyExist(beauty)){
                // 织布中的美女排除
                if (!player.getModule(ColdRoomModule.class).isBeautyFree(beauty.getBeautyId())){
                    continue;
                }
                randomList.add(beauty);
            }
        }
        return randomList;
    }

    /**
     * 获取可随机美女集合 (排除【织布中的】，【才艺等级满级的】)
     * @return
     */
    public List<UserBeauty> getRandomAddEscortExpBeautyList() {
        List<UserBeauty> randomList = new ArrayList<>();
        for(UserBeauty beauty : userBeautyMap.values()){
            if(BeautyMgr.isUserBeautyExist(beauty)){
                // 织布中的美女排除
                if (!player.getModule(ColdRoomModule.class).isBeautyFree(beauty.getBeautyId())){
                    continue;
                }
                // 才艺等级满级
                if (this.checkEscortLevelFull(beauty)){
                    continue;
                }
                randomList.add(beauty);
            }
        }
        return randomList;
    }

    public UserBeauty getFirstIndexBeauty(){
        List<UserBeauty> dataList = new ArrayList<>(userBeautyMap.values());
        if(dataList.size() > 0){
            return dataList.get(0);
        }
        return null;
    }

    /**
     * 执行传唤，增加美女经验
     */
    private BeautyTrystGain tryst(UserBeauty userBeauty,boolean notifyTask) {
        BeautyTrystGain trystGain = new BeautyTrystGain();
        if (reduceEnergy()) {
            long addExp = BeautyMgr.getAddBeautyExp(player, userBeauty);
            MammonEffectResult effectResult = player.getModule(MammonModule.class).isMammonSkillEffect(eSkillType.MammonBeautyExpAddition.getValue(), addExp);
            if(effectResult.getEffectMammonSkill() > 0){
                addExp = effectResult.getValue();
            }
            trystGain.setEffectMammonSkill(effectResult.getEffectMammonSkill());
            trystGain.setAddExp((int) addExp);
            trystGain.setBeautyId(userBeauty.getBeautyId());
            //是否产生子女
            DailyDataModule dailyDataModule = player.getModule(DailyDataModule.class);
            if(player.getModule(CardModule.class).isTrystMakeDoubleChild(dailyDataModule.getWeekCardTrystTimes())){//每日前几次传唤美女生双胞胎
                UserChildSite child = player.getModule(ChildModule.class).beautyMakeChild(userBeauty, true);
                if (null != child) {
                    trystGain.setChildUid(child.getChildUid());
                    trystGain.setMultiChild(true);
                }
                dailyDataModule.addWeekCardTrystTimes(1);
                dailyDataModule.syncWeekCardDailyData();
            }else {
                if (player.getModule(TravelModule.class).isMakeMultiChild()) {//游历生双胞胎
                    UserChildSite child = player.getModule(ChildModule.class).beautyMakeChild(userBeauty, true);
                    if (null != child) {
                        player.getModule(TravelModule.class).removeMakeMultiChildEvent();//移除双胞胎事件
                        trystGain.setChildUid(child.getChildUid());
                        trystGain.setMultiChild(true);
                        trystGain.setTravelEventMultiChild(true);
                    }
                } else if (BeautyMgr.isTrystMakeChild(player)) {
                    UserChildSite child = player.getModule(ChildModule.class).beautyMakeChild(userBeauty, false);
                    if (null != child) {
                        trystGain.setChildUid(child.getChildUid());
                        if (child.getChildType() > 0) {
                            trystGain.setMultiChild(true);
                        }
                    }
                }
            }
            //产出经验
//            player.getModule(CurrencyModule.class).addCurrency(new Property(GameConfig.GAME_MONEY_BEAUTY_EXP, BigInteger.valueOf(addExp)),
//                    eLogMoneyType.Beauty, eLogMoneyType.BeautyTryst);
            userBeauty.setSkillExp(userBeauty.getSkillExp()+addExp);
            //增加累计传唤次数
            userBeauty.setTotalTrystTimes(userBeauty.getTotalTrystTimes() + 1);
            //成就、任务 总次数总是会变的 无所谓了
            player.notifyListener(eGamePlayerEventType.BeautyTotalTrystTimes.getValue(), new BeautyArgs(userBeautyMap));
            if (notifyTask) {    //如果不是找回奖励就加任务
                player.notifyListener(eGamePlayerEventType.BeautyTrystTimes.getValue(), 1);
                player.notifyListener(eGamePlayerEventType.UnionBeautyTrystTimes.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, 1, player.getUserInfo().getUnionUid()));
                //小面任务
                player.getModule(XiaoMianModule.class).addBeautyTrystTimes(1);
            }
            syncUserBeauty(userBeauty);
        }
        return trystGain;
    }

    /**
     * 宠幸()
     */
    private BeautyFavorGain favor(UserBeauty userBeauty,int type) {
        BeautyFavorGain favorGain = new BeautyFavorGain();
        long addExp = BeautyMgr.getAddBeautyExp(player, userBeauty);
        if(type == 1){//出游
            addExp = addExp * (1000 + GameConfig.BEAUTY_FAVOR_TRAVEL_ADD)/1000;
            // 加答题奖励
            addGlamour(userBeauty,ConfigMgr.getBeautyTravelGuessFailReward(), eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorGuessAddGlamourGoods.getValue());
            userBeauty.setGuessTimes(1);
            favorGain.setGuessTimes(1);

        }else if(type == 2){//沐浴
            addExp = addExp * (1000 + GameConfig.BEAUTY_FAVOR_BATH_ADD)/1000;
            // 加答题奖励
            addGlamour(userBeauty,ConfigMgr.getBeautyTravelPoetryFailReward(), eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorPoetryAddGlamourGoods.getValue());
            userBeauty.setPoetryTimes(1);
            favorGain.setPoetryTimes(1);
        }
        favorGain.setAddExp((int) addExp);
        favorGain.setBeautyId(userBeauty.getBeautyId());
        UserChildSite child = player.getModule(ChildModule.class).beautyMakeChild(userBeauty,type == 2);
        if(child != null){
            favorGain.setChildUid(child.getChildUid());
            log.info(player.getUserId()+"宠幸，是否必双胞胎"+(type == 2)+"美女id"+userBeauty.getBeautyId());
        }else{
            log.info(player.getUserId()+"没有位置的宠幸，是否必双胞胎"+(type == 2)+"美女id"+userBeauty.getBeautyId());
        }

        userBeauty.setSkillExp(userBeauty.getSkillExp()+addExp);

        return favorGain;
    }

    /**
     * 获取精力值
     */
    private int getBeautyEnergy() {
        calcEnergy();
        return userBeautyData.getEnergy();
    }

    /**
     * 扣除精力值
     */
    private boolean reduceEnergy() {
        calcEnergy();
        if (userBeautyData.getEnergy() > 0) {
            userBeautyData.setEnergy(userBeautyData.getEnergy() - 1);
            syncBeautyEnergy();
            try {
                mistressRecoveryTime();
            }catch (Exception e){
                log.error("error:" + e);
            }
            return true;
        }
        return false;
    }

    //算出什么时间精力会自动恢复满，可以和美女出游微信提示
    private void mistressRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long nowTime = System.currentTimeMillis();
        long recoveryTime = 0;

        int maxEnergy = getBeautyMaxEnergy();
        long energyRestoreTime = getBeautyEnergyRestoreTime() * 1000;
        if(userBeautyData.getEnergy() < maxEnergy){
            recoveryTime = nowTime + energyRestoreTime * (maxEnergy - userBeautyData.getEnergy());
        }
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setMistressTime(recoveryTime);
    }

    public Map<Integer, UserBeauty> getBeautyMap() {
        return new ConcurrentHashMap<>(userBeautyMap);
    }

    private BeautyProto.GetEnergyRespMsg.Builder getEnergyData() {
        BeautyProto.GetEnergyRespMsg.Builder msg = BeautyProto.GetEnergyRespMsg.newBuilder();
        // 获取之前 计算一次
        int energy = getBeautyEnergy();
        msg.setEnergy(energy);
        if (energy >= getBeautyMaxEnergy()) {
            msg.setLastRestoreTime(0);
        } else {
            msg.setLastRestoreTime(userBeautyData.getLastRestoreTime());
        }
        return msg;
    }

    /**
     * 计算精力恢复
     */
    private void calcEnergy() {
        long nowTime = System.currentTimeMillis() / 1000;
        long lastRestoreTime = userBeautyData.getLastRestoreTime();
        int maxEnergy = getBeautyMaxEnergy();
        int energyRestoreTime = getBeautyEnergyRestoreTime();
        if(userBeautyData.getEnergy() < maxEnergy){
            //恢复次数
            int restoreTimes = (int) ((nowTime - lastRestoreTime) / energyRestoreTime);
            if (restoreTimes < 0) {
                restoreTimes = 0;
            }
            int energy = userBeautyData.getEnergy();
            // 当前值 + 恢复指 如果超过最大值
            if (restoreTimes + energy >= maxEnergy) {
                energy = maxEnergy;
                userBeautyData.setLastRestoreTime(nowTime);
            } else {
                energy = energy + restoreTimes;
                userBeautyData.setLastRestoreTime(lastRestoreTime + energyRestoreTime * restoreTimes);
            }
            userBeautyData.setEnergy(energy);
        }else {
            userBeautyData.setLastRestoreTime(nowTime);
        }
    }

    public UserBeautyData getUserBeautyData() {
        return userBeautyData;
    }

    public UserBeauty getUserBeauty(int beautyId) {
        return userBeautyMap.get(beautyId);
    }

    public int getBeautyCount(){
        int count = 0;
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            if (BeautyMgr.isUserBeautyExist(userBeauty)) {
                count++;
            }
        }
        return count;
    }

    public void recoverEnergy(GoodsInfo goodsInfo, long count) {
        long addCount = goodsInfo.getParamList().get(0).longValue() * count;
        userBeautyData.setEnergy((int) (getBeautyEnergy() + addCount));
        syncBeautyEnergy();
        try {
            mistressRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    public void recoverEnergy(int count) {
        userBeautyData.setEnergy(getBeautyEnergy() + count);
        syncBeautyEnergy();
        try {
            mistressRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    /**
     * 美女精力上限
     */
    private int getBeautyMaxEnergy(){
        int energy;
        TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
        energy = titleInfo.getBeautyAddEnergy();
        if(0 == energy){
            energy = GameConfig.BEAUTY_MAX_ENERGY_VALUE;
        }
        energy += CurioMgr.getSkillAdditionBySkillType(eSkillType.CurioBeautyEnergyLimitAddSkill.getValue(), player, 0);
        return energy;
    }

    /**
     * 美女精力恢复时间
     */
    private int getBeautyEnergyRestoreTime(){
        int time;
        TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
        time = titleInfo.getBeautyEnergyRestoreTimeLower();
        time -= CurioMgr.getSkillAdditionBySkillType(eSkillType.CurioBeautyEnergyAddSkill.getValue(), player, 0);
        if(0 == time){
            time = GameConfig.BEAUTY_RESTORE_ENERGY_TIME;
        }
        return time;
    }

    private UserBeautySkill initUserBeautySkill(long userId, int beautyId, int skillPos, int skillValue, int skillModifyTimes) {
        UserBeautySkill userBeautySkill = new UserBeautySkill();
        userBeautySkill.setUserId(userId);
        userBeautySkill.setBeautyId(beautyId);
        userBeautySkill.setSkillPos(skillPos);
        userBeautySkill.setSkillValue(skillValue);
        userBeautySkill.setSkillModifyTimes(skillModifyTimes);
        userBeautySkill.setInsertOption();
        return userBeautySkill;
    }

    private int getUnlockBeautyCount(){
        int count = 0;
        if(null != userBeautyMap){
            for(UserBeauty userBeauty : userBeautyMap.values()){
                if(BeautyMgr.isUserBeautyExist(userBeauty)){
                    count++;
                }
            }
        }
        return count;
    }

    public int getNoMakeChildTimes(){
        if(null != userBeautyData){
            return userBeautyData.getNoMakeChildTimes();
        }
        return 0;
    }

    public void addNoMakeChildTimes(){
        if(null != userBeautyData){
            userBeautyData.setNoMakeChildTimes(userBeautyData.getNoMakeChildTimes() + 1);
        }
    }

    public void resetNoMakeChildTimes(){
        if(null != userBeautyData){
            userBeautyData.setNoMakeChildTimes(0);
        }
    }

    /**
     * 跟指定门客相关的变化
     */
    private void onBeautyChange(UserBeauty userBeauty) {
        if(null != userBeauty){
            List<UserBeauty> userBeautyList = new ArrayList<>();
            userBeautyList.add(userBeauty);
            onBeautyListChange(userBeautyList);
        }else {
            player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        }
    }

    /**
     * 跟指定门客相关的变化
     */
    public void onBeautyListChange(List<UserBeauty> userBeautyList) {
        if(null != userBeautyList && userBeautyList.size() > 0){
            Map<Integer, UserPatrons> patronsMap = player.getModule(PatronsModule.class).getUserPatronsMap();
            List<UserPatrons> patronsList = new ArrayList<>();
            for(UserBeauty userBeauty : userBeautyList) {
                for (UserPatrons userPatrons : patronsMap.values()) {
                    if (BeautyMgr.beautyAndPatronsHasRelation(userBeauty, userPatrons)) {//与美女关联的
                        patronsList.add(userPatrons);
                    }
                }
            }
            if(patronsList.size() > 0){
                player.getModule(PatronsModule.class).onPatronsListChange(patronsList);
            }else {
                player.getModule(EarnSpeedModule.class).scheduleAddSilver();
            }
        }
    }

    private void beautyChange(UserBeauty userBeauty) {
        try {
            if (userBeauty != null) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", userBeauty.getBeautyId());
                jsonObject.put("skinId", userBeauty.getSkinId());
                jsonObject.put("lv", userBeauty.getIdentitySkillLv());
                jsonObject.put("qua", userBeauty.getQuality());
                RankMgr.changeUserRank(eBigRankType.Beauty.getValue(), player.getUserId(), BigInteger.valueOf(userBeauty.getTotalIntimacy()), eRankType.Beauty.getValue(), jsonObject.toJSONString());
                RankMgr.changeUserRank(eBigRankType.Beauty.getValue(), player.getUserId(), BigInteger.valueOf(userBeauty.getTotalIntimacy()), userBeauty.getBeautyId(), jsonObject.toJSONString());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public boolean checkBeautyList(List<Integer> beautyList){
        List<Integer> addBeautyIdList = new ArrayList<>();
        for(Integer beautyId : beautyList){
            if(!userBeautyMap.containsKey(beautyId)){
                return false;
            }
            if(addBeautyIdList.contains(beautyId)){
                return false;
            }
            addBeautyIdList.add(beautyId);
        }
        return true;
    }

    //获取派遣的特殊数据
    public Map<Integer,List<Integer>> getDispatchList(List<Integer> beautyIdList){
        Map<Integer,List<Integer>> occupationQualityMap = new ConcurrentHashMap<>();
        //所有职业的
        occupationQualityMap.put(0,new ArrayList<>());
        for(Integer beautyId : beautyIdList){
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
            UserBeauty userBeauty = getUserBeauty(beautyId);
            if(beautyInfo == null || null == userBeauty)continue;
            if(!occupationQualityMap.containsKey(beautyInfo.getOccupation())){
                occupationQualityMap.put(beautyInfo.getOccupation(),new ArrayList<>());
            }
            occupationQualityMap.get(beautyInfo.getOccupation()).add(userBeauty.getQuality());
            occupationQualityMap.get(0).add(userBeauty.getQuality());
        }
        return occupationQualityMap;
    }

    /**
     * 穿皮肤
     * @param beautyId
     * @param skinId
     * @return
     */
    public int putOnSkin(int beautyId, int skinId) {
        // 判断美女是否的存在
        UserBeauty userBeauty = userBeautyMap.get(beautyId);
        if (userBeauty == null) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        // skinId = 0表示脱衣服
        if (skinId == 0) {
            userBeauty.setSkinId(0);
            syncUserBeauty(userBeauty);
            return 0;
        }

        // 判断是否有这个皮肤
        if (!player.getModule(SkinModule.class).isSkinExist(skinId)) {
            return GameErrorCode.E_SKIN_IS_NOT_UNLOCK;
        }

        // 判断皮肤配置
        SkinInfo skinInfo = SkinMgr.getSkinInfoMap().get(skinId);
        if (skinInfo == null) {
            return GameErrorCode.E_SKIN_NOT_EXIST;
        }

        // 判断皮肤类型
        if (eSkinType.Beauty.getValue() != skinInfo.getType()) {
            return GameErrorCode.E_SKIN_TYPE_ERROR;
        }

        // 判断美女皮肤归属
        if (skinInfo.getBelongRole() != userBeauty.getBeautyId()) {
            return GameErrorCode.E_SKIN_IS_NOT_BELONG_TO_BEAUTY;
        }

        userBeauty.setSkinId(skinId);
        syncUserBeauty(userBeauty);
        return 0;
    }

    /**
     * 获取美女名称
     */
    public String getBeautyName(int beautyId, String language) {
        // 前缀暂时写死
        return MultipleLanguageMgr.getContent("Beauty-" + beautyId, language);
    }

    @Override
    public void afterLogin() {
        syncAllBeautyVoice(userBeautyVoiceMap);
        checkBeautyResource();
        for (Map.Entry<Integer, UserBeauty> beautyEntry : getBeautyMap().entrySet()) {
            UserBeauty userBeauty = beautyEntry.getValue();
            //修复品质晋升id
            if(userBeauty.getPeerlessUp() > 0 && userBeauty.getQualityPromotionId() == 0){
                //晋升过无双
                List<PromotionInfo> listPromotion = PromotionMgr.getCharacterPromotion(userBeauty.getBeautyId());
                if(listPromotion != null){
                    PromotionInfo startPromotionInfo = null;
                    for (PromotionInfo promotionInfo : listPromotion) {
                        if (promotionInfo.getType() == 11 || promotionInfo.getType() == 13) {//无双晋升类型11、13
                            startPromotionInfo = promotionInfo;
                            break;
                        }
                    }
                    PromotionInfo currPromotionInfo = startPromotionInfo;
                    if(currPromotionInfo != null) {
                        int promotionAmount = userBeauty.getPeerlessUp();
                        for (int i = 0; i < promotionAmount - 1; i++) {
                            PromotionInfo promotionInfo = PromotionMgr.getPromotionInfoById(currPromotionInfo.getNextId());
                            if (promotionInfo != null) {
                                currPromotionInfo = promotionInfo;
                            } else {
                                break;
                            }
                        }
                        userBeauty.setQualityPromotionId(currPromotionInfo.getId());
                        log.info("repair user {} beauty {} setQualityPromotionId to {}", player.getUserId(), userBeauty.getBeautyId(), currPromotionInfo.getId());
                    }
                }
            }

            checkBeautyMusicRoomSkill(userBeauty);

            beautyChange(beautyEntry.getValue());
        }

        reCalcBeautyTotalRelationPatronsAddAbility();
    }

    private void checkBeautyResource() {
        if (userBeautyMap != null) {
            for (UserBeauty beauty : userBeautyMap.values()) {
                addBeautyFlag(beauty.getBeautyId());
            }
        }
    }

    private void addBeautyFlag(int beautyId) {
        player.getModule(GoodsResourceModule.class).addResource(beautyId, BeautyMgr.getLinkType(beautyId));
    }

    /**
     * 获取玩家亲密度最高的美女 如果亲密一样 比较魅力 如果魅力还一样比较id
     * @return
     */
    public UserBeauty getMaxIntimacyUserBeauty(){
        UserBeauty maxIntimacyUserBeauty = null;
        if (userBeautyMap != null) {
            for (UserBeauty beauty : userBeautyMap.values()) {
                if(maxIntimacyUserBeauty == null){
                    maxIntimacyUserBeauty = beauty;
                    continue;
                }
                if(maxIntimacyUserBeauty.getTotalIntimacy() < beauty.getTotalIntimacy()){
                    // 比较亲密
                    maxIntimacyUserBeauty = beauty;
                }else if(maxIntimacyUserBeauty.getTotalIntimacy() == beauty.getTotalIntimacy()){
                    if(maxIntimacyUserBeauty.getGlamour() < beauty.getGlamour()){
                        // 比较魅力
                        maxIntimacyUserBeauty = beauty;
                    }else if(maxIntimacyUserBeauty.getGlamour() == beauty.getGlamour()){
                        if(maxIntimacyUserBeauty.getBeautyId() < beauty.getBeautyId()){
                            // 比较id
                            maxIntimacyUserBeauty = beauty;
                        }
                    }
                }
            }
        }
        return maxIntimacyUserBeauty;
    }


    /**
     * 技能改装自动化
     *
     * @param beautyId    美女id
     * @param skillPos    技能位置
     * @param isCustomize 是否定制
     * @param goalVal     目标值
     * @param costLimit   消耗上限
     */
    public BeautyModifySkillResult beautySkillModifyAuto(int beautyId, int skillPos, boolean isCustomize, long goalVal, String costLimit, boolean isBegin) {
        if (isBegin) {
            playerBeautyAutoModifyCost.clear();
        }
        BeautyModifySkillResult res = new BeautyModifySkillResult();
        if (player.getTitleId() < GameConfig.BEAUTY_SKILL_ONE_KEY_MODIFY_NEED_TITLE) {
            res.setRet(GameErrorCode.E_TITLE_LEVEL_NO_ENOUGH);
            return res;
        }
        //目标限制
        UserBeauty userBeauty = getUserBeauty(beautyId);
        if (!BeautyMgr.isUserBeautyExist(userBeauty)) {
            res.setRet(GameErrorCode.E_BEAUTY_NO_FOUND);
            return res;
        }
        UserBeautySkill skill = userBeauty.getSkillMap().get(skillPos);
        if (skill == null) {
            res.setRet(GameErrorCode.E_BEAUTY_SKILL_NO_FOUND);
            return res;
        }
        res.setBeautySkill(skill);
        if (skill.getSkillValue() >= goalVal) {
            res.setRet(GameErrorCode.E_BEAUTY_SKILL_VALUE_LIMIT);
            return res;
        }
        //消耗上限
        if (!isCustomize) {
            BigInteger silver = BeautyMgr.getModifySkillCost(skill.getSkillModifyTimes());
            if (silver.compareTo(new BigInteger(costLimit)) > 0) {
                res.setRet(GameErrorCode.E_BEAUTY_SKILL_MODIFY_COST_LIMIT);
                return res;
            }
        }
        return beautyModifySkill(beautyId, skillPos, isCustomize, true);
    }

    public void stopVehicleSkillModifyAuto(BeautyProto.StopBeautySkillModifyAutoRespMsg.Builder respMsg) {
        Property cost = new Property();
        cost.addProperty(GameConfig.BEAUTY_SKILL_CUSTOM_MODIFY_ITEM, BigInteger.valueOf(playerBeautyAutoModifyCost.getItemCost()));
        cost.addProperty(GameConfig.GAME_MONEY_SILVER, BigInteger.valueOf(playerBeautyAutoModifyCost.getSliverCost()));
        respMsg.setCost(PropertyHelper.parsePropertyToString(cost));
        playerBeautyAutoModifyCost.clear();
    }

    /**
     * 宠幸答题
     */
    public BeautyPalyProto.BeautyFavorAnswerRespMsg.Builder beautyFavorAnswer(List<BeautyPalyProto.BeautyFavorAnswerEntity> answerList) {
        BeautyPalyProto.BeautyFavorAnswerRespMsg.Builder builder = BeautyPalyProto.BeautyFavorAnswerRespMsg.newBuilder();
        Set<UserBeauty> syncBeautySet = new HashSet<>();
        for (BeautyPalyProto.BeautyFavorAnswerEntity item : answerList){
            UserBeauty userBeauty = getUserBeauty(item.getBeautyId());
            if(userBeauty != null){
                if(item.getType() == 0 && userBeauty.getGuessTimes() >0 ){
                    // 灯谜
                    if(item.getRight()){
                        // 加奖励，国服因为共用了和其它服的宠幸代码，已经加过了默认答错题的奖励，要在这里先扣除掉
                        int addValue = ConfigMgr.getBeautyTravelGuessSuccessReward() - ConfigMgr.getBeautyTravelGuessFailReward();
                        addGlamour(userBeauty,addValue, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorGuessAddGlamourGoods.getValue());
                        syncBeautySet.add(userBeauty);
                    }
                    userBeauty.setGuessTimes(userBeauty.getGuessTimes() - 1);
                }else if(item.getType() == 1 && userBeauty.getPoetryTimes() >0){
                    // 吟诗
                    if(item.getRight()){
                        int addValue = ConfigMgr.getBeautyTravelPoetrySuccessReward() - ConfigMgr.getBeautyTravelPoetryFailReward();
                        addGlamour(userBeauty,addValue, eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorPoetryAddGlamourGoods.getValue());
                        syncBeautySet.add(userBeauty);
                    }
                    userBeauty.setPoetryTimes(userBeauty.getPoetryTimes() - 1);
                }
            }
        }
        player.getModule(BeautyModule.class).syncUserBeauty(new ArrayList<>(syncBeautySet), false);
        builder.setRet(0);
        return builder;
    }

    public List<UserBeauty> getUserBeautyListByOccupation(int occupation) {
        List<UserBeauty> list = new ArrayList<>();
        for (UserBeauty beauty : new ArrayList<>(userBeautyMap.values())) {
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beauty.getBeautyId());
            if (beautyInfo.getOccupation() == occupation) {
                list.add(beauty);
            }
        }
        return list;
    }

    /**
     * 普通晋升传奇品质
     */
    public int beautyQualityUp(int beautyId) {
        UserBeauty userBeauty = userBeautyMap.get(beautyId);
        if (!BeautyMgr.isUserBeautyExist(userBeauty)) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        List<PromotionInfo> listPromotion = PromotionMgr.getCharacterPromotion(beautyId);
        if (null == listPromotion) {
            return GameErrorCode.E_ERROR_DATA;
        }

        //待晋升
        PromotionInfo promotionInfo = null;
        for (PromotionInfo target : listPromotion) {
            if (target.getType() == 12 && userBeauty.getQuality() < target.getQuality()) {
                promotionInfo = target;
                break;
            }
        }
        if (null == promotionInfo) {
            return GameErrorCode.E_ERROR_DATA;
        }else if(promotionInfo.getId() <= userBeauty.getQualityPromotionId() && userBeauty.getQualityPromotionId() > 0){
            return GameErrorCode.E_ERROR_DATA;
        }

        //晋升条件
        List<String> conditionList = StringUtils.stringToStringList(promotionInfo.getParamList(), "\\|");
        if(conditionList.size() != 2){
            return GameErrorCode.E_ERROR_DATA;
        }

        List<Integer> peerlessSkinConditions = StringUtils.stringToIntegerList(conditionList.get(0), ";");

        List<Integer> normalSkinConditions = StringUtils.stringToIntegerList(conditionList.get(0), ";");

        if(peerlessSkinConditions.size() != 2 || normalSkinConditions.size() != 2){
            return GameErrorCode.E_ERROR_DATA;
        }

        //需要无双皮数量
        int peerlessSkinNeed = peerlessSkinConditions.get(0);
        //需要无双皮等级
        int peerlessSkinLevel = peerlessSkinConditions.get(1);

        //普通皮数量
        int normalSkinNeed = normalSkinConditions.get(0);
        int normalSkinLevel = normalSkinConditions.get(1);

        List<UserSkin> skinList = player.getModule(SkinModule.class).getUserSkinListByBeautyId(beautyId);
        for (UserSkin userSkin : skinList) {
            SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
            if (null == skinInfo) {
                continue;
            }
            if (skinInfo.isPeerless() == 1) {
                if (userSkin.getLevel() >= peerlessSkinLevel){
                    peerlessSkinNeed--;
                }
            }else {
                if (userSkin.getLevel() >= normalSkinLevel){
                    normalSkinNeed--;
                }
            }
        }

        if(peerlessSkinNeed > 0 || normalSkinNeed > 0){
            return GameErrorCode.E_SKIN_NOT_MATCH;
        }

        userBeauty.setQuality(promotionInfo.getQuality());
        userBeauty.setQualityPromotionId(promotionInfo.getId());

        player.getModule(MusicRoomModule.class).refreshBeautyAttr(userBeauty);

        //解锁缘分
        //List<BeautyRelation> relationList = BeautyMgr.getBeautyRelationListByPromotion(2, promotionInfo.getId());

        return 0;
    }

    /**
     * 无双晋升
     */
    public int beautyPeerlessUp(int beautyId) {
        UserBeauty userBeauty = userBeautyMap.get(beautyId);
        if (!BeautyMgr.isUserBeautyExist(userBeauty)) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        List<PromotionInfo> listPromotion = PromotionMgr.getCharacterPromotion(beautyId);
        if (null == listPromotion) {
            return GameErrorCode.E_ERROR_DATA;
        }
        PromotionInfo startPromotionInfo = null;
        for (PromotionInfo promotionInfo : listPromotion) {
            if (promotionInfo.getType() == 11 || promotionInfo.getType() == 13) {//无双晋升类型11、13
                startPromotionInfo = promotionInfo;
                break;
            }
        }

        if (null == startPromotionInfo) {
            return GameErrorCode.E_ERROR_DATA;
        }
        PromotionInfo nextPromotionInfo = startPromotionInfo;
        List<PromotionInfo> unlockPromotions = new ArrayList<>();
        unlockPromotions.add(startPromotionInfo);
        int promotionAmount = userBeauty.getPeerlessUp();
        for (int i = 0; i < promotionAmount; i++) {
            nextPromotionInfo = PromotionMgr.getPromotionInfoById(nextPromotionInfo.getNextId());
            unlockPromotions.add(nextPromotionInfo);
        }

        if (null == nextPromotionInfo) {
            //没有下一级了
            return GameErrorCode.E_ERROR_DATA;
        }else if(nextPromotionInfo.getId() <= userBeauty.getQualityPromotionId() && userBeauty.getQualityPromotionId() > 0){
            //无需晋升
            return GameErrorCode.E_ERROR_DATA;
        }

        if (nextPromotionInfo.getType() == 11) {
            //找晋升需求
            //        参数格式：晋升条件=技能id1=升级条件#升级条件
            //        示例配置：1;1|4;1=60101=1;2|4;2#1;3|4;3
            //        解锁技能60101
            //        1;1|4;1 表示 1件强化等级≥1的无双皮肤| 4件强化等级≥1的普通皮肤
            //        晋升条件：1件强化等级≥1的无双皮肤| 4件强化等级≥1的普通皮肤
            //        升级条件：1件强化等级≥2的无双皮肤| 4件强化等级≥2的普通皮肤

            String[] arrStrs = nextPromotionInfo.getParamList().split("=");
            if (arrStrs.length < 3) {
                return GameErrorCode.E_ERROR_DATA;
            }
            String[] promotionStrs = arrStrs[0].split("\\|");
            if (promotionStrs.length != 2) {
                return GameErrorCode.E_ERROR_DATA;
            }
            String[] peerlessAttrs = promotionStrs[0].split(";");
            if (peerlessAttrs.length != 2) {
                return GameErrorCode.E_ERROR_DATA;
            }
            String[] normalAttrs = promotionStrs[1].split(";");
            if (normalAttrs.length != 2) {
                return GameErrorCode.E_ERROR_DATA;
            }
            //需要无双皮数量
            int peerlessSkinNeed = Integer.valueOf(peerlessAttrs[0]);
            //需要无双皮等级
            int peerlessSkinLevel = Integer.valueOf(peerlessAttrs[1]);

            //普通皮数量
            int normalSkinNeed = Integer.valueOf(normalAttrs[0]);
            int normalSkinLevel = Integer.valueOf(normalAttrs[1]);

            List<UserSkin> skinList = player.getModule(SkinModule.class).getUserSkinListByBeautyId(beautyId);
            for (UserSkin userSkin : skinList) {
                SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
                if (null == skinInfo) {
                    continue;
                }
                if (skinInfo.isPeerless() == 1) {
                    if (userSkin.getLevel() >= peerlessSkinLevel && peerlessSkinNeed > 0) {
                        peerlessSkinNeed--;
                    }
                } else {
                    if (userSkin.getLevel() >= normalSkinLevel && normalSkinNeed > 0) {
                        normalSkinNeed--;
                    }
                }
            }

            if (peerlessSkinNeed != 0 || normalSkinNeed != 0) {//皮肤要求不满足
                return GameErrorCode.E_SKIN_NOT_MATCH;
            }
        } else if (nextPromotionInfo.getType() == 13) {
            //        13 美女晋升无双渠道
//            孔位技能;孔位1三生技能,孔位2三生技能,孔位3三生技能|等级需求；等级需求；等级需求；等级需求；等级需求
            ItemPeerlessPromotionInfo itemPeerlessPromotionInfo = nextPromotionInfo.getItemPeerlessPromotionInfo();
            if (itemPeerlessPromotionInfo == null) {
                return GameErrorCode.E_ERROR_PARAMETER;
            }
            int needSkillNum = userBeauty.getPeerlessUp() + 1;
            int needLv = itemPeerlessPromotionInfo.getPeerlessSkillLvUpNeedPromotionSkillLv(1);

            for (int pos = 1; pos <= itemPeerlessPromotionInfo.getPromotionSkills().size(); pos++) {
                int promoteSkillLevelByPos = userBeauty.getPromoteSkillLevelByPos(pos);
                if (promoteSkillLevelByPos >= needLv) {
                    needSkillNum --;
                }
            }
            if (needSkillNum > 0) {//晋升技能等级要求不满足
                return GameErrorCode.E_ERROR_DATA;
            }
        }
        //解锁孔位数
        int unlockNum = unlockPromotions.size();
        userBeauty.setQuality(nextPromotionInfo.getQuality());
        userBeauty.setQualityPromotionId(nextPromotionInfo.getId());
        userBeauty.setPeerlessUp(userBeauty.getPeerlessUp() + 1);
        for (int i = 0; i < unlockNum; i++) {
            userBeauty.addPeerlessSkillLevelIfNull(i + 1);
        }

        //解锁自选缘分门客孔位
        if (nextPromotionInfo.getSelfSelectPatronsPositionNum() > 0) {
            this.addBeautySelfSelectPatronsPosition(beautyId);
        }

        AutoLogMgr.add(new LogBeautyPeerlessUp(player.getUserId(), beautyId, userBeauty.getPeerlessUp() - 1, userBeauty.getPeerlessUp()));

        player.getModule(MusicRoomModule.class).refreshBeautyAttr(userBeauty);

        player.getModule(CurioModule.class).checkAllCurioItemSpecialSkill();
        return 0;
    }

    /**
     * @param beautyId  美女id
     * @param position  孔位
     * @param patronsId 门客id
     * @return 错误码
     */
    public int peerlessBindPatrons(int beautyId, int position, int patronsId) {
        UserBeauty userBeauty = userBeautyMap.get(beautyId);
        if (!BeautyMgr.isUserBeautyExist(userBeauty)) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        BeautyPeerlessSkillInfo peerlessSkillInfo = userBeauty.getPeerlessSkill(position);
        if (null == peerlessSkillInfo) {
            return GameErrorCode.E_BEAUTY_PEERLESS_PATRONS_POSITION_ERR;
        }

        //cd期间允许操作
        int now = DateHelper.getCurrentSecond();
        if(peerlessSkillInfo.getCd() > 0){
            if(now < peerlessSkillInfo.getCd()){
                return GameErrorCode.E_PATRONS_PEERLESS_PATRONS_RELATION_CD;
            }
        }

        int oldPatronsId = peerlessSkillInfo.getPatronsId();
        if (oldPatronsId == patronsId) {
            return GameErrorCode.E_BEAUTY_PEERLESS_PATRONS_EXISTS;
        }

        UserPatrons selectPatrons = null;
        if(patronsId > 0) {
            selectPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
            if (selectPatrons == null) {
                return GameErrorCode.E_PATRONS_NO_FOUND;
            }

            if (!BeautyMgr.beautyAndPatronsHasRelationNotCondition(userBeauty, selectPatrons)) {
                return GameErrorCode.E_PATRONS_NO_FOUND;
            }
        }

        if(patronsId > 0) {
            peerlessSkillInfo.setCd(now + GameConfig.BEAUTY_PEERLESS_PATRONS_CHANGE_CD * 3600);
        }

        peerlessSkillInfo.setPatronsId(patronsId);
        userBeauty.setUpdateOption();
        onBeautyChange(userBeauty);

        AutoLogMgr.add(new LogBeautyPeerlessBind(player.getUserId(), beautyId, patronsId));

        List<UserPatrons> changeList = new ArrayList<>();

        if(selectPatrons != null) {
            changeList.add(selectPatrons);
        }

        if(oldPatronsId > 0){
            changeList.add(player.getModule(PatronsModule.class).getUserPatrons(oldPatronsId));
        }
        player.getModule(PatronsModule.class).onPatronsListChange(changeList);

        return 0;
    }



    public int beautyGenderSwap(int beautyId, int genderSwapMark) {
        UserBeauty userBeauty = getUserBeauty(beautyId);
        if(!BeautyMgr.isUserBeautyExist(userBeauty)){
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
        if(null == beautyInfo){
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }
        if(beautyInfo.getGenderSwapId() <= 0){
            return GameErrorCode.E_BEAUTY_CAN_NO_GENDER_SWAP;
        }
        int oldMark = userBeauty.getGenderSwapMark();
        userBeauty.setGenderSwapMark(genderSwapMark);
        if(oldMark != genderSwapMark){//切换就要恢复初始皮肤
            userBeauty.setSkinId(0);
        }
        return 0;
    }


    public BeautyTrystResult retrieveRewards(int times) {
        userBeautyData.setEnergy(userBeautyData.getEnergy() + times); //先给他加体力
        BeautyTrystResult result = new BeautyTrystResult();
        for (int i = 0; i < times; i++) {
            BeautyTrystGain gain = randomTryst(false);
            result.addResult(gain);
        }
        return result;
    }

    public int getLastSaveTimePower(){
        return lastSaveTimePower;
    }

    /**
     * 初始化美女妙音坊门客技能
     * @param userBeauty
     */
    public boolean checkBeautyMusicRoomSkill(UserBeauty userBeauty) {
        List<BeautyIdentityInfo> beautyIdentityInfoList = BeautyMgr.getBeautyIdentityInfoListLessThenLv(userBeauty.getIdentityLv());
        if (beautyIdentityInfoList.isEmpty()) {
            return false;
        }
        boolean isChange = false;
        Set<Integer> realUnlockSkillList = new HashSet<>();
        if (SystemOpenMgr.systemOpen(player, eSystemId.MusicRoom.getValue())) {
            for (BeautyIdentityInfo beautyIdentityInfo : beautyIdentityInfoList) {
                for (BeautyMusicRoomSkillInfo musicRoomSkillInfo : beautyIdentityInfo.getMusicRoomSkill()) {
                    int skillId = musicRoomSkillInfo.getSkillId();
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (skillInfo == null) {
                        continue;
                    }
                    int musicRoomSkillLevel = userBeauty.getMusicRoomSkillLevel(skillId);

                    if (musicRoomSkillInfo.getUnlockNeedSkillId() != 0) {
                        int unlockSkillLevel = userBeauty.getMusicRoomSkillLevel(musicRoomSkillInfo.getUnlockNeedSkillId());
                        if (unlockSkillLevel < musicRoomSkillInfo.getUnlockLevel()) {//前置技能等级不够
                            if (musicRoomSkillLevel > 0) {
                                log.error("妙音坊门客技能脏数据了 userId={},beautyId={},skillId={},level={}", player.getUserId(), userBeauty.getBeautyId(), skillId, musicRoomSkillLevel);
                                userBeauty.setMusicRoomSkillLevel(skillId, 0);
                            }
                            continue;
                        }
                    }

                    if (musicRoomSkillLevel == 0) {
                        userBeauty.setMusicRoomSkillLevel(skillId, 1);
                        isChange = true;
                    }
                    musicRoomSkillLevel = userBeauty.getMusicRoomSkillLevel(skillId);
                    if (musicRoomSkillLevel > 0) {
                        realUnlockSkillList.add(skillId);
                    }
                }
            }
        }


        List<Integer> needRemoveIds = new ArrayList<>();
        for (Map.Entry<Integer, BigInteger> entry : userBeauty.getMusicRoomSkill().getGoods().entrySet()) {
            int skillId = entry.getKey();
            if (!realUnlockSkillList.contains(skillId)) {
                needRemoveIds.add(skillId);
            }
        }

        for (Integer skillId : needRemoveIds) {
            int musicRoomSkillLevel = userBeauty.getMusicRoomSkillLevel(skillId);
            //清理脏数据用
            log.error("妙音坊门客技能脏数据了 userId={},beautyId={},skillId={},level={}", player.getUserId(), userBeauty.getBeautyId(), skillId, musicRoomSkillLevel);
            userBeauty.setMusicRoomSkillLevel(skillId, 0);
        }
        return isChange;
    }

    public void checkAllBeautyMusicRoomSkill(){
        List<UserBeauty> needSyncList = new ArrayList<>();
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            if(checkBeautyMusicRoomSkill(userBeauty)){
                needSyncList.add(userBeauty);
            }
        }
        syncUserBeauty(needSyncList, false);
    }

    /**
     * 增加美女才艺经验
     * @param userBeauty
     * @param addExp
     */
    public void addBeautyEscortExp(UserBeauty userBeauty, long addExp) {
        //增加才艺经验
        userBeauty.setEscortExp(userBeauty.getEscortExp() + addExp);
//        //todo:延期上线，先注释。判断是否才艺等级满级，满级才转换成道具
//        if (addExp > 0) {
//            this.escortLevelFullExpHandle(userBeauty);
//        }
    }

    /**
     * 判断技能是否满级
     * @param skillInfo
     * @param skillLevel
     * @return ture：满级，false：未满级
     */
    private boolean checkSkillLevelFull(SkillInfo skillInfo, int skillLevel) {
        SkillUpgradeInfo nextUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), skillLevel + 1);
        if (nextUpgradeInfo == null) {
            return true;
        }
        return false;
    }

    /**
     * 判断押镖才艺技能是否满级
     * @param userBeauty
     * @return
     */
    public boolean checkEscortLevelFull(UserBeauty userBeauty) {
        boolean levelFullFlag = true;
        //判断2才艺等级都满级
        List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
        for (int skillId : skillList) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            int skillLevel;
            if (skillId == 60002) {
                skillLevel = userBeauty.getEscortSkill1();
            } else {
                skillLevel = userBeauty.getEscortSkill2();
            }
            boolean skillLevelFullFlag = this.checkSkillLevelFull(skillInfo, skillLevel);
            if (!skillLevelFullFlag) {
                levelFullFlag = false;
            }
        }
        return levelFullFlag;
    }

    /**
     * 才艺等级满级全满级后，溢出押镖经验转经验道具
     * @param userBeauty 美女
     * @return 道具
     */
    public void escortLevelFullExpHandle(UserBeauty userBeauty) {
        //判断2才艺等级都满级
        boolean levelFullFlag = this.checkEscortLevelFull(userBeauty);
        //押镖经验转道具
        if (levelFullFlag) {
            //清空经验
            long exp = userBeauty.getEscortExp();
            userBeauty.setEscortExp(0);
            //日志
            AutoLogMgr.add(new LogBeautySkillExp(player.getUserId(), userBeauty.getBeautyId(), -exp, userBeauty.getEscortExp(), eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyEscortExpFullTransformEmpty.getValue()));
            //todo：经验道具。道具ID未定义
            Property property = new Property(GameConfig.ESCORT_EXP_TRANSFORM_PROP_ID, exp);
            //邮件发送奖励
            String reward = PropertyHelper.parsePropertyToString(property);
            String mailTitle = MultipleLanguageMgr.getContent(MailManager.BEAUTY_ESCORT_EXP_FULL_TRANSFORM_TITLE, player.getLanguage());
            String mailContent = MultipleLanguageMgr.getContent(MailManager.BEAUTY_ESCORT_EXP_FULL_TRANSFORM_CONTENT, player.getLanguage());
            MailManager.sendMail(player.getUserId(), eMailType.DAILY.getValue(), reward, mailContent, mailTitle);
            //同步一下
            player.getModule(BeautyModule.class).syncUserBeauty(userBeauty);
        }
    }

    /**
     * 获取无双美女晋升配置
     * @return PromotionInfo
     */
    private PromotionInfo getPeerlessBeautyPromotionInfo(UserBeauty userBeauty) {
        //获取美女晋升配置LIST
        List<PromotionInfo> listPromotion = PromotionMgr.getCharacterPromotion(userBeauty.getBeautyId());
        if(listPromotion != null){
            PromotionInfo startPromotionInfo = null;
            for (PromotionInfo promotionInfo : listPromotion) {
                if (promotionInfo.getType() == 11 || promotionInfo.getType() == 13) {//无双晋升类型11、13
                    startPromotionInfo = promotionInfo;
                    break;
                }
            }
            PromotionInfo currPromotionInfo = startPromotionInfo;
            if(currPromotionInfo != null) {
                int promotionAmount = userBeauty.getPeerlessUp();
                for (int i = 0; i < promotionAmount - 1; i++) {
                    PromotionInfo promotionInfo = PromotionMgr.getPromotionInfoById(currPromotionInfo.getNextId());
                    if (promotionInfo != null) {
                        currPromotionInfo = promotionInfo;
                    } else {
                        break;
                    }
                }
            }
            return currPromotionInfo;
        }
        return null;
    }

    /**
     * 添加自选缘分门客孔位
     */
    public synchronized void addBeautySelfSelectPatronsPosition(int beautyId) {
        //获取美女
        UserBeauty userBeauty = this.userBeautyMap.get(beautyId);
        if (userBeauty == null) {
            return;
        }
        //获取美女孔位数量
        PromotionInfo promotionInfo = this.getPeerlessBeautyPromotionInfo(userBeauty);
        if (promotionInfo == null || promotionInfo.getSelfSelectPatronsPositionNum() <= 0) {
            return;
        }
        //判断孔位数量是否达上限
        Map<Integer, BeautySelfSelectPatronsPosition> selfSelectPatronsMap = userBeauty.getSelfSelectPatronsMap();
        if (selfSelectPatronsMap.size() >= promotionInfo.getSelfSelectPatronsPositionNum()) {
            return;
        }
        //新增孔位的数量
        int addNum = promotionInfo.getSelfSelectPatronsPositionNum() - selfSelectPatronsMap.size();
        for (int i = 0; i < addNum; i++) {
            //新增孔位
            int newPositionId = selfSelectPatronsMap.size() + 1;
            BeautySelfSelectPatronsPosition selfSelectPatronsInfo = new BeautySelfSelectPatronsPosition();
            selfSelectPatronsInfo.setId(newPositionId);
            selfSelectPatronsInfo.setPatronsId(0);
            selfSelectPatronsInfo.setCd(0);
            userBeauty.putSelfSelectPatrons(selfSelectPatronsInfo);
        }
    }

    /**
     * 保存自选缘分门客
     * @param beautyId
     * @param patronsId
     * @param position
     * @throws BusinessException
     */
    public BeautySelfSelectPatronsPosition saveSelfSelectPatrons(int beautyId, int patronsId, int position) throws BusinessException {
        //获取美女
        UserBeauty userBeauty = this.userBeautyMap.get(beautyId);
        if (userBeauty == null) {
            throw BusinessException.newException(GameErrorCode.E_BEAUTY_NO_FOUND);
        }
        //获取门客
        UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
        if (userPatrons == null) {
            throw BusinessException.newException(GameErrorCode.E_PATRONS_NO_FOUND);
        }
        //判断是否被锲约，被契约不能成为自选美女
        for (UserPatronsContract userPatronsContract : userPatrons.getPatronsContractMap().values()) {
            if (userPatronsContract.getBeautyId() == beautyId) {
                throw BusinessException.newException(GameErrorCode.E_PATRONS_SAVE_RELATION_NOT_CONTRACT);
            }
        }

        //获取孔位
        BeautySelfSelectPatronsPosition patronsPosition = userBeauty.getSelfSelectPatronsMap().get(position);
        if (patronsPosition == null) {
            throw BusinessException.newException(GameErrorCode.E_BEAUTY_SELF_SELECT_PATRONS_POSITION_NOT_FOUND);
        }
        //判断是否cd中
        if (patronsPosition.getCd() >= DateHelper.getCurrentSecond()) {
            throw BusinessException.newException(GameErrorCode.E_BEAUTY_SELF_SELECT_PATRONS_WAITING_CD);
        }
        //判断是否是已存在的缘分
        boolean alreadyFlag = BeautyMgr.beautyAndPatronsHasRelationNotCondition(userBeauty, userPatrons);
        if (alreadyFlag) {
            throw BusinessException.newException(GameErrorCode.E_BEAUTY_SELF_SELECT_PATRONS_ALREADY_IN_POOL);
        }

        //旧的自选门客ID
        int oldPatronsId = patronsPosition.getPatronsId();

        //注入
        patronsPosition.setPatronsId(patronsId);
        patronsPosition.setCd(DateHelper.getCurrentSecond() + GameConfig.BEAUTY_PEERLESS_ADD_PATRONS_CHANGE_CD * 3600);
        userBeauty.putSelfSelectPatrons(patronsPosition);

        //判断旧的自选的门客是否在无双缘分中，有的话，去掉无双缘分
        if (oldPatronsId > 0) {
            boolean needUpdate = false;
            Map<Integer, BeautyPeerlessSkillInfo> peerlessSkillMap = userBeauty.getPeerlessSkillMap();
            for (BeautyPeerlessSkillInfo peerlessSkillInfo : peerlessSkillMap.values()) {
                if (peerlessSkillInfo.getPatronsId() == oldPatronsId) {
                    peerlessSkillInfo.setPatronsId(0);
                    needUpdate = true;
                }
            }
            if (needUpdate) {
                userBeauty.setUpdateOption();
            }
            //旧门客赚钱变化
            UserPatrons oldPatrons = player.getModule(PatronsModule.class).getUserPatrons(oldPatronsId);
            player.getModule(PatronsModule.class).onPatronsChange(oldPatrons);
        }
        //赚钱变化处理
        onBeautyChange(userBeauty);
        return patronsPosition;
    }

    /**
     * 获得门客的缘分美女
     */
    public List<UserBeauty> getPatronsRelationBeauty(UserPatrons userPatrons) {
        List<UserBeauty> list = new ArrayList<>();
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(userBeauty, userPatrons)) {//缘分美女
                list.add(userBeauty);
            }
        }
        return list;
    }

    /**
     * 获得门客被契约的缘分美女
     * @param userPatrons
     * @return beautyId=patronsId
     */
    public Map<Integer, Integer> getPatronsBeContractBeauty(UserPatrons userPatrons) {
        Map<Integer, Integer> resultMap = new HashMap<>();
        if (userPatrons == null) {
            return resultMap;
        }

        for (UserBeauty userBeauty : userBeautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(userBeauty, userPatrons)) {//缘分美女
                int contractBeautyPatronsId = player.getModule(PatronsModule.class).getContractBeautyPatronsId(userBeauty.getBeautyId());
                if (contractBeautyPatronsId != 0) {
                    resultMap.put(userBeauty.getBeautyId(), contractBeautyPatronsId);
                }
            }
        }

        return resultMap;
    }

    /**
     * 计算并更新美女的总缘分门客加成,只计算被锲约的美女
     */
    public void reCalcBeautyTotalRelationPatronsAddAbility() {
        CalcPatronsAbilityParam calcPatronsAbilityParam = player.getModule(PatronsModule.class).buildCalcPatronsAbilityParam();
        for (UserBeauty userBeauty : userBeautyMap.values()) {
            UserPatrons contractBeautyPatrons = player.getModule(PatronsModule.class).getContractBeautyPatrons(userBeauty.getBeautyId());
            if (contractBeautyPatrons != null) {
                BigDecimal oldAbility = userBeauty.getTotalRelationPatronsAbility();
                BigDecimal ability = BeautyMgr.calcBeautyTotalAddRelationPatronsAbility(userBeauty, calcPatronsAbilityParam);
                if (oldAbility.compareTo(ability) != 0) {
                    userBeauty.setTotalRelationPatronsAbility(ability);
                }
            }
        }
    }

    /**
     * 只计算被锲约的美女
     * @param userBeauty
     * @param calcPatronsAbilityParam
     */
    public void reCalcBeautyTotalRelationPatronsAddAbility(UserBeauty userBeauty, CalcPatronsAbilityParam calcPatronsAbilityParam) {
        UserPatrons contractBeautyPatrons = player.getModule(PatronsModule.class).getContractBeautyPatrons(userBeauty.getBeautyId());
        if (contractBeautyPatrons != null) {
            BigDecimal oldAbility = userBeauty.getTotalRelationPatronsAbility();
            BigDecimal ability = BeautyMgr.calcBeautyTotalAddRelationPatronsAbility(userBeauty, calcPatronsAbilityParam);
            if (oldAbility.compareTo(ability) != 0) {
                userBeauty.setTotalRelationPatronsAbility(ability);

                if (oldAbility.compareTo(BigDecimal.ZERO) != 0) {
                    player.getModule(PatronsModule.class).syncPatronsCache(Collections.singletonList(contractBeautyPatrons));
                }
            }
        }
    }


    /**
     * 美女一键宠幸
     *
     * @param beautyIdList 美女ID列表
     * @param type         宠幸类型
     * @param count        宠幸次数
     * @return BeautyFavorResult
     */
    public BeautyFavorResult beautyQuickFavor(List<Integer> beautyIdList, int type, int count) {
        Property cost = getFavorCost(beautyIdList, type, count); // 需要消耗的道具
        if (!player.getModule(CurrencyModule.class).currencyIsEnough(cost)) {
            BeautyFavorResult result = new BeautyFavorResult();
            result.setRet(GameErrorCode.E_BEAUTY_FAVOR_COST);
            if (2 == type) { // 沐浴道具不足，触发现金礼包
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            }
            return result;
        }

        return favorAll(beautyIdList, type, cost, count);
    }

    /**
     * 获取宠幸消耗
     *
     * @param beautyIdList 美女ID列表
     * @param type         宠幸类型
     * @param count        宠幸次数
     * @return Property
     */
    private Property getFavorCost(List<Integer> beautyIdList, int type, int count) {
        Property cost = new Property();

        if (type == 1) { // 出游
            int needMoney = 0;
            for (int beautyId : beautyIdList) {
                UserBeauty userBeauty = getUserBeauty(beautyId);
                needMoney += BeautyMgr.getTravelCost(userBeauty.getTravelTimes(), count);
            }
            cost.addProperty(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(needMoney));
        } else if (type == 2) { // 沐浴
            cost.addProperty(PropertyHelper.parseStringToProperty(GameConfig.BEAUTY_FAVOR_BATH_COST));
            cost.rideProperty(beautyIdList.size() * count);
        }

        return cost;
    }

    /**
     * 多次宠幸
     *
     * @param beautyIdList 美女ID列表
     * @param type         出游类型
     * @param cost         消耗道具
     * @param count        出游次数
     * @return BeautyFavorResult
     */
    private BeautyFavorResult favorAll(List<Integer> beautyIdList, int type, Property cost, int count) {
        BeautyFavorResult favorResult = new BeautyFavorResult();

        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.Beauty, eLogMoneyType.BeautyFavor)) {
            favorResult.setRet(GameErrorCode.E_BEAUTY_FAVOR_COST);
            if (2 == type) {//沐浴道具不足，触发现金礼包
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCount.getValue(), 0);
                player.notifyListener(eGamePlayerEventType.RechargeBeautyCountNew.getValue(), 0);
            }
            return favorResult;
        }

        for (Integer beautyId : beautyIdList) {
            UserBeauty userBeauty = getUserBeauty(beautyId);
            for (int i = 0; i < count; i++) {
                BeautyFavorGain gain = favorForBatch(userBeauty, type);
                favorResult.addResult(gain);
                if (type == 1) { // 出游
                    userBeauty.setTravelTimes(userBeauty.getTravelTimes() + 1);
                    player.notifyListener(eGamePlayerEventType.BeautyTotalTravelTimes.getValue(), new BeautyArgs(userBeautyMap));
                    player.notifyListener(eGamePlayerEventType.BeautyTotalFavorTimes.getValue(), new BeautyArgs(userBeautyMap));

                    AutoLogMgr.add(new LogBeautyFavor(player.getUserId(), userBeauty.getBeautyId(), type, userBeauty.getTravelTimes(),
                            PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(BeautyMgr.getTravelCost(userBeauty.getTravelTimes())))),
                            PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_BEAUTY_EXP, BigInteger.valueOf(gain.getAddExp())))));

                    DataAnalyticsMgr.trackBeautyTrip(player, userBeauty, type);
                } else if (type == 2) { // 沐浴
                    userBeauty.setBathTimes(userBeauty.getBathTimes() + 1);
                    player.notifyListener(eGamePlayerEventType.BeautyTotalBathTimes.getValue(), new BeautyArgs(userBeautyMap));
                    player.notifyListener(eGamePlayerEventType.BeautyTotalFavorTimes.getValue(), new BeautyArgs(userBeautyMap));

                    AutoLogMgr.add(new LogBeautyFavor(player.getUserId(), userBeauty.getBeautyId(), type, userBeauty.getBathTimes(),
                            GameConfig.BEAUTY_FAVOR_BATH_COST,
                            PropertyHelper.parsePropertyToString(new Property(GameConfig.GAME_MONEY_BEAUTY_EXP, BigInteger.valueOf(gain.getAddExp())))));

                    DataAnalyticsMgr.trackBeautyTrip(player, userBeauty, type);
                }
                syncUserBeauty(userBeauty);
            }
        }

        return favorResult;
    }

    /**
     * 多次
     *
     * @param userBeauty 美女信息
     * @param type       宠幸类型
     * @return BeautyFavorGain
     */
    private BeautyFavorGain favorForBatch(UserBeauty userBeauty, int type) {
        BeautyFavorGain favorGain = new BeautyFavorGain();
        long addExp = BeautyMgr.getAddBeautyExp(player, userBeauty);
        if (type == 1) {//出游
            addExp = addExp * (1000 + GameConfig.BEAUTY_FAVOR_TRAVEL_ADD) / 1000;
            // 加答题奖励
            addGlamour(userBeauty, ConfigMgr.getBeautyTravelGuessFailReward(), eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorGuessAddGlamourGoods.getValue());
            userBeauty.setGuessTimes(userBeauty.getGuessTimes() + 1);
            favorGain.setGuessTimes(userBeauty.getGuessTimes() + 1);

        } else if (type == 2) {//沐浴
            addExp = addExp * (1000 + GameConfig.BEAUTY_FAVOR_BATH_ADD) / 1000;
            // 加答题奖励
            addGlamour(userBeauty, ConfigMgr.getBeautyTravelPoetryFailReward(), eLogMoneyType.Beauty.getValue(), eLogMoneyType.BeautyFavorPoetryAddGlamourGoods.getValue());
            userBeauty.setPoetryTimes(userBeauty.getPoetryTimes() + 1);
            favorGain.setPoetryTimes(userBeauty.getPoetryTimes() + 1);
        }
        favorGain.setAddExp((int) addExp);
        favorGain.setBeautyId(userBeauty.getBeautyId());
        UserChildSite child = player.getModule(ChildModule.class).beautyMakeChild(userBeauty, type == 2);
        if (child != null) {
            favorGain.setChildUid(child.getChildUid());
            log.info(player.getUserId() + "宠幸，是否必双胞胎" + (type == 2) + "美女id" + userBeauty.getBeautyId());
        } else {
            log.info(player.getUserId() + "没有位置的宠幸，是否必双胞胎" + (type == 2) + "美女id" + userBeauty.getBeautyId());
        }

        userBeauty.setSkillExp(userBeauty.getSkillExp() + addExp);

        return favorGain;
    }

    /**
     * 获取前几美女
     * @param topCount
     * @type 1 亲密  2 魅力 3 所有
     * @return
     */
    public List<UserBeauty> getTopIntimacyBeauty(int topCount, int type) {
        List<UserBeauty> userBeauty = new ArrayList<>(getUserBeautyMap().values());
        List<UserBeauty> resultList = new ArrayList<>();

        if(type == 1) {
            userBeauty.sort((o1, o2) -> Integer.compare(o2.getTotalIntimacy(), o1.getTotalIntimacy()));
        }else if(type == 2){
            userBeauty.sort((o1, o2) -> Integer.compare(o2.getTotalGlamour(), o1.getTotalGlamour()));
        }else if(type == 3){
            //先按亲密排序
            userBeauty.sort((o1, o2) -> Integer.compare(o2.getTotalIntimacy(), o1.getTotalIntimacy()));
            //再按亲密+魅力
            userBeauty.sort((o1, o2) -> Integer.compare(o2.getTotalGlamour() + o2.getTotalIntimacy(), o1.getTotalGlamour() + o1.getTotalIntimacy()));
        }

        for (UserBeauty beauty : userBeauty) {
            resultList.add(beauty);
            if (--topCount <= 0) {
                break;
            }
        }

        return resultList;
    }
}
